Make DomainVerificationManager a final class

Makes testing a little more difficult, but mirrors the other system
service classes.

Bug: 181101101

Test: atest com.android.server.pm.test.verify.domain

Change-Id: I39a3c2160943a0a6c77fe792446ed2f1407fb0e0
This commit is contained in:
Winson
2021-02-24 14:14:25 -08:00
parent c28d1fee5e
commit 6a4df7f5e2
10 changed files with 218 additions and 318 deletions

View File

@@ -2769,7 +2769,7 @@ package android.content.pm.verify.domain {
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.verify.domain.DomainVerificationInfo> CREATOR;
}
public interface DomainVerificationManager {
public final class DomainVerificationManager {
method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.DOMAIN_VERIFICATION_AGENT, android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION}) public android.content.pm.verify.domain.DomainVerificationInfo getDomainVerificationInfo(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
method @Nullable @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public android.content.pm.verify.domain.DomainVerificationUserSelection getDomainVerificationUserSelection(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION) public java.util.List<android.content.pm.verify.domain.DomainOwner> getOwnersForDomain(@NonNull String);

View File

@@ -71,7 +71,6 @@ import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutManager;
import android.content.pm.verify.domain.DomainVerificationManager;
import android.content.pm.verify.domain.DomainVerificationManagerImpl;
import android.content.pm.verify.domain.IDomainVerificationManager;
import android.content.res.Resources;
import android.content.rollback.RollbackManagerFrameworkInitializer;
@@ -1432,7 +1431,7 @@ public final class SystemServiceRegistry {
Context.DOMAIN_VERIFICATION_SERVICE);
IDomainVerificationManager service =
IDomainVerificationManager.Stub.asInterface(binder);
return new DomainVerificationManagerImpl(context, service);
return new DomainVerificationManager(context, service);
}
});

View File

@@ -25,8 +25,11 @@ import android.annotation.SystemService;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -53,34 +56,35 @@ import java.util.UUID;
*/
@SystemApi
@SystemService(Context.DOMAIN_VERIFICATION_SERVICE)
public interface DomainVerificationManager {
public final class DomainVerificationManager {
/**
* Extra field name for a {@link DomainVerificationRequest} for the requested packages.
* Passed to an the domain verification agent that handles
* {@link Intent#ACTION_DOMAINS_NEED_VERIFICATION}.
*/
String EXTRA_VERIFICATION_REQUEST =
public static final String EXTRA_VERIFICATION_REQUEST =
"android.content.pm.verify.domain.extra.VERIFICATION_REQUEST";
/**
* No response has been recorded by either the system or any verification agent.
*/
int STATE_NO_RESPONSE = DomainVerificationState.STATE_NO_RESPONSE;
public static final int STATE_NO_RESPONSE = DomainVerificationState.STATE_NO_RESPONSE;
/** The verification agent has explicitly verified the domain at some point. */
int STATE_SUCCESS = DomainVerificationState.STATE_SUCCESS;
public static final int STATE_SUCCESS = DomainVerificationState.STATE_SUCCESS;
/**
* The first available custom response code. This and any greater integer, along with
* {@link #STATE_SUCCESS} are the only values settable by the verification agent. All values
* will be treated as if the domain is unverified.
*/
int STATE_FIRST_VERIFIER_DEFINED = DomainVerificationState.STATE_FIRST_VERIFIER_DEFINED;
public static final int STATE_FIRST_VERIFIER_DEFINED =
DomainVerificationState.STATE_FIRST_VERIFIER_DEFINED;
/** @hide */
@NonNull
static String stateToDebugString(@DomainVerificationState.State int state) {
public static String stateToDebugString(@DomainVerificationState.State int state) {
switch (state) {
case DomainVerificationState.STATE_NO_RESPONSE:
return "none";
@@ -107,7 +111,7 @@ public interface DomainVerificationManager {
* Checks if a state considers the corresponding domain to be successfully verified. The
* domain verification agent may use this to determine whether or not to re-verify a domain.
*/
static boolean isStateVerified(@DomainVerificationState.State int state) {
public static boolean isStateVerified(@DomainVerificationState.State int state) {
switch (state) {
case DomainVerificationState.STATE_SUCCESS:
case DomainVerificationState.STATE_APPROVED:
@@ -129,7 +133,7 @@ public interface DomainVerificationManager {
* this method to determine if a state can be changed without having to be aware of what the
* new state means.
*/
static boolean isStateModifiable(@DomainVerificationState.State int state) {
public static boolean isStateModifiable(@DomainVerificationState.State int state) {
switch (state) {
case DomainVerificationState.STATE_NO_RESPONSE:
case DomainVerificationState.STATE_SUCCESS:
@@ -151,7 +155,7 @@ public interface DomainVerificationManager {
* no behavior is made based on the result.
* @hide
*/
static boolean isStateDefault(@DomainVerificationState.State int state) {
public static boolean isStateDefault(@DomainVerificationState.State int state) {
switch (state) {
case DomainVerificationState.STATE_NO_RESPONSE:
case DomainVerificationState.STATE_MIGRATED:
@@ -167,6 +171,30 @@ public interface DomainVerificationManager {
}
}
/** @hide */
public static final int ERROR_INVALID_DOMAIN_SET = 1;
/** @hide */
public static final int ERROR_NAME_NOT_FOUND = 2;
/** @hide */
@IntDef(prefix = { "ERROR_" }, value = {
ERROR_INVALID_DOMAIN_SET,
ERROR_NAME_NOT_FOUND,
})
private @interface Error {
}
private final Context mContext;
private final IDomainVerificationManager mDomainVerificationManager;
/** @hide */
public DomainVerificationManager(Context context,
IDomainVerificationManager domainVerificationManager) {
mContext = context;
mDomainVerificationManager = domainVerificationManager;
}
/**
* Used to iterate all {@link DomainVerificationInfo} values to do cleanup or retries. This is
* usually a heavy workload and should be done infrequently.
@@ -175,7 +203,13 @@ public interface DomainVerificationManager {
*/
@NonNull
@RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT)
List<String> getValidVerificationPackageNames();
public List<String> getValidVerificationPackageNames() {
try {
return mDomainVerificationManager.getValidVerificationPackageNames();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Retrieves the domain verification state for a given package.
@@ -189,8 +223,21 @@ public interface DomainVerificationManager {
android.Manifest.permission.DOMAIN_VERIFICATION_AGENT,
android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION
})
DomainVerificationInfo getDomainVerificationInfo(@NonNull String packageName)
throws NameNotFoundException;
public DomainVerificationInfo getDomainVerificationInfo(@NonNull String packageName)
throws NameNotFoundException {
try {
return mDomainVerificationManager.getDomainVerificationInfo(packageName);
} catch (Exception e) {
Exception converted = rethrow(e, packageName);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
/**
* Change the verification status of the {@param domains} of the package associated with
@@ -213,8 +260,22 @@ public interface DomainVerificationManager {
* scheduled basis.
*/
@RequiresPermission(android.Manifest.permission.DOMAIN_VERIFICATION_AGENT)
void setDomainVerificationStatus(@NonNull UUID domainSetId, @NonNull Set<String> domains,
@DomainVerificationState.State int state) throws NameNotFoundException;
public void setDomainVerificationStatus(@NonNull UUID domainSetId, @NonNull Set<String> domains,
@DomainVerificationState.State int state) throws NameNotFoundException {
try {
mDomainVerificationManager.setDomainVerificationStatus(domainSetId.toString(),
new DomainSet(domains), state);
} catch (Exception e) {
Exception converted = rethrow(e, domainSetId);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
/**
* TODO(b/178525735): This documentation is incorrect in the context of UX changes.
@@ -226,8 +287,22 @@ public interface DomainVerificationManager {
* By default, all apps are allowed to open verified links. Users must disable them explicitly.
*/
@RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION)
void setDomainVerificationLinkHandlingAllowed(@NonNull String packageName, boolean allowed)
throws NameNotFoundException;
public void setDomainVerificationLinkHandlingAllowed(@NonNull String packageName,
boolean allowed) throws NameNotFoundException {
try {
mDomainVerificationManager.setDomainVerificationLinkHandlingAllowed(packageName,
allowed, mContext.getUserId());
} catch (Exception e) {
Exception converted = rethrow(e, packageName);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
/**
* Update the recorded user selection for the given {@param domains} for the given {@param
@@ -262,8 +337,22 @@ public interface DomainVerificationManager {
* scheduled basis.
*/
@RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION)
void setDomainVerificationUserSelection(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean enabled) throws NameNotFoundException;
public void setDomainVerificationUserSelection(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean enabled) throws NameNotFoundException {
try {
mDomainVerificationManager.setDomainVerificationUserSelection(domainSetId.toString(),
new DomainSet(domains), enabled, mContext.getUserId());
} catch (Exception e) {
Exception converted = rethrow(e, domainSetId);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
/**
* Retrieve the user selection data for the given {@param packageName} and the current user.
@@ -280,8 +369,22 @@ public interface DomainVerificationManager {
*/
@Nullable
@RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION)
DomainVerificationUserSelection getDomainVerificationUserSelection(@NonNull String packageName)
throws NameNotFoundException;
public DomainVerificationUserSelection getDomainVerificationUserSelection(
@NonNull String packageName) throws NameNotFoundException {
try {
return mDomainVerificationManager.getDomainVerificationUserSelection(packageName,
mContext.getUserId());
} catch (Exception e) {
Exception converted = rethrow(e, packageName);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
/**
* For the given domain, return all apps which are approved to open it in a
@@ -294,7 +397,47 @@ public interface DomainVerificationManager {
*/
@NonNull
@RequiresPermission(android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION)
List<DomainOwner> getOwnersForDomain(@NonNull String domain);
public List<DomainOwner> getOwnersForDomain(@NonNull String domain) {
try {
return mDomainVerificationManager.getOwnersForDomain(domain, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private Exception rethrow(Exception exception, @Nullable UUID domainSetId) {
return rethrow(exception, domainSetId, null);
}
private Exception rethrow(Exception exception, @Nullable String packageName) {
return rethrow(exception, null, packageName);
}
private Exception rethrow(Exception exception, @Nullable UUID domainSetId,
@Nullable String packageName) {
if (exception instanceof ServiceSpecificException) {
int packedErrorCode = ((ServiceSpecificException) exception).errorCode;
if (packageName == null) {
packageName = exception.getMessage();
}
@Error int managerErrorCode = packedErrorCode & 0xFFFF;
switch (managerErrorCode) {
case ERROR_INVALID_DOMAIN_SET:
int errorSpecificCode = packedErrorCode >> 16;
return new IllegalArgumentException(InvalidDomainSetException.buildMessage(
domainSetId, packageName, errorSpecificCode));
case ERROR_NAME_NOT_FOUND:
return new NameNotFoundException(packageName);
default:
return exception;
}
} else if (exception instanceof RemoteException) {
return ((RemoteException) exception).rethrowFromSystemServer();
} else {
return exception;
}
}
/**
* Thrown if a {@link DomainVerificationInfo#getIdentifier()}} or an associated set of domains
@@ -305,7 +448,7 @@ public interface DomainVerificationManager {
*
* @hide
*/
class InvalidDomainSetException extends IllegalArgumentException {
public static class InvalidDomainSetException extends IllegalArgumentException {
public static final int REASON_ID_NULL = 1;
public static final int REASON_ID_INVALID = 2;

View File

@@ -1,202 +0,0 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.content.pm.verify.domain;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import java.util.List;
import java.util.Set;
import java.util.UUID;
/**
* @hide
*/
@SuppressWarnings("RedundantThrows")
public class DomainVerificationManagerImpl implements DomainVerificationManager {
public static final int ERROR_INVALID_DOMAIN_SET = 1;
public static final int ERROR_NAME_NOT_FOUND = 2;
@IntDef(prefix = { "ERROR_" }, value = {
ERROR_INVALID_DOMAIN_SET,
ERROR_NAME_NOT_FOUND,
})
private @interface Error {
}
private final Context mContext;
private final IDomainVerificationManager mDomainVerificationManager;
public DomainVerificationManagerImpl(Context context,
IDomainVerificationManager domainVerificationManager) {
mContext = context;
mDomainVerificationManager = domainVerificationManager;
}
@NonNull
@Override
public List<String> getValidVerificationPackageNames() {
try {
return mDomainVerificationManager.getValidVerificationPackageNames();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
@Nullable
@Override
public DomainVerificationInfo getDomainVerificationInfo(@NonNull String packageName)
throws NameNotFoundException {
try {
return mDomainVerificationManager.getDomainVerificationInfo(packageName);
} catch (Exception e) {
Exception converted = rethrow(e, packageName);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
@Override
public void setDomainVerificationStatus(@NonNull UUID domainSetId, @NonNull Set<String> domains,
int state) throws IllegalArgumentException, NameNotFoundException {
try {
mDomainVerificationManager.setDomainVerificationStatus(domainSetId.toString(),
new DomainSet(domains), state);
} catch (Exception e) {
Exception converted = rethrow(e, domainSetId);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
@Override
public void setDomainVerificationLinkHandlingAllowed(@NonNull String packageName,
boolean allowed) throws NameNotFoundException {
try {
mDomainVerificationManager.setDomainVerificationLinkHandlingAllowed(packageName,
allowed, mContext.getUserId());
} catch (Exception e) {
Exception converted = rethrow(e, packageName);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
@Override
public void setDomainVerificationUserSelection(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean enabled)
throws IllegalArgumentException, NameNotFoundException {
try {
mDomainVerificationManager.setDomainVerificationUserSelection(domainSetId.toString(),
new DomainSet(domains), enabled, mContext.getUserId());
} catch (Exception e) {
Exception converted = rethrow(e, domainSetId);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
@Nullable
@Override
public DomainVerificationUserSelection getDomainVerificationUserSelection(
@NonNull String packageName) throws NameNotFoundException {
try {
return mDomainVerificationManager.getDomainVerificationUserSelection(packageName,
mContext.getUserId());
} catch (Exception e) {
Exception converted = rethrow(e, packageName);
if (converted instanceof NameNotFoundException) {
throw (NameNotFoundException) converted;
} else if (converted instanceof RuntimeException) {
throw (RuntimeException) converted;
} else {
throw new RuntimeException(converted);
}
}
}
@NonNull
@Override
public List<DomainOwner> getOwnersForDomain(@NonNull String domain) {
try {
return mDomainVerificationManager.getOwnersForDomain(domain, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private Exception rethrow(Exception exception, @Nullable UUID domainSetId) {
return rethrow(exception, domainSetId, null);
}
private Exception rethrow(Exception exception, @Nullable String packageName) {
return rethrow(exception, null, packageName);
}
private Exception rethrow(Exception exception, @Nullable UUID domainSetId,
@Nullable String packageName) {
if (exception instanceof ServiceSpecificException) {
int packedErrorCode = ((ServiceSpecificException) exception).errorCode;
if (packageName == null) {
packageName = exception.getMessage();
}
@Error int managerErrorCode = packedErrorCode & 0xFFFF;
switch (managerErrorCode) {
case ERROR_INVALID_DOMAIN_SET:
int errorSpecificCode = packedErrorCode >> 16;
return new IllegalArgumentException(InvalidDomainSetException.buildMessage(
domainSetId, packageName, errorSpecificCode));
case ERROR_NAME_NOT_FOUND:
return new NameNotFoundException(packageName);
default:
return exception;
}
} else if (exception instanceof RemoteException) {
return ((RemoteException) exception).rethrowFromSystemServer();
} else {
return exception;
}
}
}

View File

@@ -48,7 +48,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.function.Function;
public interface DomainVerificationManagerInternal extends DomainVerificationManager {
public interface DomainVerificationManagerInternal {
UUID DISABLED_ID = new UUID(0, 0);
@@ -69,8 +69,8 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan
* during the legacy transition period.
*
* TODO(b/177923646): The legacy values can be removed once the Settings API changes are
* shipped. These values are not stable, so just deleting the constant and shifting others is
* fine.
* shipped. These values are not stable, so just deleting the constant and shifting others is
* fine.
*/
int APPROVAL_LEVEL_LEGACY_ASK = 1;
@@ -84,14 +84,15 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan
/**
* The app has been chosen by the user through
* {@link #setDomainVerificationUserSelection(UUID, Set, boolean)}, indictag an explicit
* choice to use this app to open an unverified domain.
* {@link DomainVerificationManager#setDomainVerificationUserSelection(UUID, Set, boolean)},
* indicating an explicit choice to use this app to open an unverified domain.
*/
int APPROVAL_LEVEL_SELECTION = 2;
/**
* The app is approved through the digital asset link statement being hosted at the domain
* it is capturing. This is set through {@link #setDomainVerificationStatus(UUID, Set, int)} by
* it is capturing. This is set through
* {@link DomainVerificationManager#setDomainVerificationStatus(UUID, Set, int)} by
* the domain verification agent on device.
*/
int APPROVAL_LEVEL_VERIFIED = 3;
@@ -102,7 +103,7 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan
* declares against the digital asset link statements before allowing it to be installed.
*
* The user is still able to disable instant app link handling through
* {@link #setDomainVerificationLinkHandlingAllowed(String, boolean)}.
* {@link DomainVerificationManager#setDomainVerificationLinkHandlingAllowed(String, boolean)}.
*/
int APPROVAL_LEVEL_INSTANT_APP = 4;
@@ -122,7 +123,17 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan
APPROVAL_LEVEL_VERIFIED,
APPROVAL_LEVEL_INSTANT_APP
})
@interface ApprovalLevel{}
@interface ApprovalLevel {
}
/** @see DomainVerificationManager#getDomainVerificationInfo(String) */
@Nullable
@RequiresPermission(anyOf = {
android.Manifest.permission.DOMAIN_VERIFICATION_AGENT,
android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION
})
DomainVerificationInfo getDomainVerificationInfo(@NonNull String packageName)
throws NameNotFoundException;
/**
* Generate a new domain set ID to be used for attaching new packages.
@@ -173,9 +184,9 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan
/**
* Migrates verification state from a previous install to a new one. It is expected that the
* {@link PackageSetting#getDomainSetId()} already be set to the correct value, usually from
* {@link #generateNewId()}. This will preserve {@link #STATE_SUCCESS} domains under the
* assumption that the new package will pass the same server side config as the previous
* package, as they have matching signatures.
* {@link #generateNewId()}. This will preserve {@link DomainVerificationManager#STATE_SUCCESS}
* domains under the assumption that the new package will pass the same server side config as
* the previous package, as they have matching signatures.
* <p>
* This will mutate internal {@link DomainVerificationPkgState} and so will hold the internal
* lock. This should never be called from within the domain verification classes themselves.
@@ -229,8 +240,10 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan
* tag has already been entered.
* <p>
* This is <b>only</b> for restore, and will override package states, ignoring if their {@link
* DomainVerificationInfo#getIdentifier()}s match. It's expected that any restored domains marked
* as success verify against the server correctly, although the verification agent may decide to
* DomainVerificationInfo#getIdentifier()}s match. It's expected that any restored domains
* marked
* as success verify against the server correctly, although the verification agent may decide
* to
* re-verify them when it gets the chance.
*/
/*

View File

@@ -23,8 +23,8 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.verify.domain.DomainOwner;
import android.content.pm.verify.domain.DomainSet;
import android.content.pm.verify.domain.DomainVerificationInfo;
import android.content.pm.verify.domain.DomainVerificationManager;
import android.content.pm.verify.domain.DomainVerificationManager.InvalidDomainSetException;
import android.content.pm.verify.domain.DomainVerificationManagerImpl;
import android.content.pm.verify.domain.DomainVerificationUserSelection;
import android.content.pm.verify.domain.IDomainVerificationManager;
import android.os.ServiceSpecificException;
@@ -32,12 +32,12 @@ import android.os.ServiceSpecificException;
import java.util.List;
import java.util.UUID;
class DomainVerificationManagerStub extends IDomainVerificationManager.Stub {
public class DomainVerificationManagerStub extends IDomainVerificationManager.Stub {
@NonNull
private DomainVerificationService mService;
private final DomainVerificationService mService;
DomainVerificationManagerStub(DomainVerificationService service) {
public DomainVerificationManagerStub(DomainVerificationService service) {
mService = service;
}
@@ -117,13 +117,13 @@ class DomainVerificationManagerStub extends IDomainVerificationManager.Stub {
private RuntimeException rethrow(Exception exception) throws RuntimeException {
if (exception instanceof InvalidDomainSetException) {
int packedErrorCode = DomainVerificationManagerImpl.ERROR_INVALID_DOMAIN_SET;
int packedErrorCode = DomainVerificationManager.ERROR_INVALID_DOMAIN_SET;
packedErrorCode |= ((InvalidDomainSetException) exception).getReason() << 16;
return new ServiceSpecificException(packedErrorCode,
((InvalidDomainSetException) exception).getPackageName());
} else if (exception instanceof NameNotFoundException) {
return new ServiceSpecificException(
DomainVerificationManagerImpl.ERROR_NAME_NOT_FOUND);
DomainVerificationManager.ERROR_NAME_NOT_FOUND);
} else if (exception instanceof RuntimeException) {
return (RuntimeException) exception;
} else {

View File

@@ -34,6 +34,7 @@ import android.content.pm.parsing.component.ParsedActivity;
import android.content.pm.verify.domain.DomainOwner;
import android.content.pm.verify.domain.DomainVerificationInfo;
import android.content.pm.verify.domain.DomainVerificationManager;
import android.content.pm.verify.domain.DomainVerificationManager.InvalidDomainSetException;
import android.content.pm.verify.domain.DomainVerificationState;
import android.content.pm.verify.domain.DomainVerificationUserSelection;
import android.content.pm.verify.domain.IDomainVerificationManager;
@@ -208,7 +209,6 @@ public class DomainVerificationService extends SystemService
}
@NonNull
@Override
public List<String> getValidVerificationPackageNames() {
mEnforcer.assertApprovedVerifier(mConnection.getCallingUid(), mProxy);
List<String> packageNames = new ArrayList<>();
@@ -272,7 +272,6 @@ public class DomainVerificationService extends SystemService
}
}
@Override
public void setDomainVerificationStatus(@NonNull UUID domainSetId, @NonNull Set<String> domains,
int state) throws InvalidDomainSetException, NameNotFoundException {
if (state < DomainVerificationState.STATE_FIRST_VERIFIER_DEFINED) {
@@ -415,13 +414,6 @@ public class DomainVerificationService extends SystemService
}
}
@Override
public void setDomainVerificationLinkHandlingAllowed(@NonNull String packageName,
boolean allowed) throws NameNotFoundException {
setDomainVerificationLinkHandlingAllowed(packageName, allowed,
mConnection.getCallingUserId());
}
public void setDomainVerificationLinkHandlingAllowed(@NonNull String packageName,
boolean allowed, @UserIdInt int userId) throws NameNotFoundException {
if (!mEnforcer.assertApprovedUserSelector(mConnection.getCallingUid(),
@@ -476,14 +468,6 @@ public class DomainVerificationService extends SystemService
mConnection.scheduleWriteSettings();
}
@Override
public void setDomainVerificationUserSelection(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean enabled)
throws InvalidDomainSetException, NameNotFoundException {
setDomainVerificationUserSelection(domainSetId, domains, enabled,
mConnection.getCallingUserId());
}
public void setDomainVerificationUserSelection(@NonNull UUID domainSetId,
@NonNull Set<String> domains, boolean enabled, @UserIdInt int userId)
throws InvalidDomainSetException, NameNotFoundException {
@@ -641,14 +625,6 @@ public class DomainVerificationService extends SystemService
}
}
@Nullable
@Override
public DomainVerificationUserSelection getDomainVerificationUserSelection(
@NonNull String packageName) throws NameNotFoundException {
return getDomainVerificationUserSelection(packageName,
mConnection.getCallingUserId());
}
@Nullable
@Override
public DomainVerificationUserSelection getDomainVerificationUserSelection(
@@ -699,12 +675,6 @@ public class DomainVerificationService extends SystemService
}
}
@NonNull
@Override
public List<DomainOwner> getOwnersForDomain(@NonNull String domain) {
return getOwnersForDomain(domain, mConnection.getCallingUserId());
}
public List<DomainOwner> getOwnersForDomain(@NonNull String domain, @UserIdInt int userId) {
mEnforcer.assertOwnerQuerent(mConnection.getCallingUid(), mConnection.getCallingUserId(),
userId);

View File

@@ -208,25 +208,12 @@ class DomainVerificationEnforcerTest {
DomainVerificationManager.STATE_SUCCESS
)
},
service(Type.SELECTOR, "setLinkHandlingAllowed") {
setDomainVerificationLinkHandlingAllowed(it.targetPackageName, true)
},
service(Type.SELECTOR_USER, "setLinkHandlingAllowedUserId") {
setDomainVerificationLinkHandlingAllowed(it.targetPackageName, true, it.userId)
},
service(Type.SELECTOR, "getUserSelection") {
getDomainVerificationUserSelection(it.targetPackageName)
},
service(Type.SELECTOR_USER, "getUserSelectionUserId") {
getDomainVerificationUserSelection(it.targetPackageName, it.userId)
},
service(Type.SELECTOR, "setUserSelection") {
setDomainVerificationUserSelection(
it.targetDomainSetId,
setOf("example.com"),
true
)
},
service(Type.SELECTOR_USER, "setUserSelectionUserId") {
setDomainVerificationUserSelection(
it.targetDomainSetId,
@@ -244,10 +231,6 @@ class DomainVerificationEnforcerTest {
service(Type.LEGACY_QUERENT, "getLegacyUserState") {
getLegacyState(it.targetPackageName, it.userId)
},
service(Type.OWNER_QUERENT, "getOwnersForDomain") {
// Re-use package name, since the result itself isn't relevant
getOwnersForDomain(it.targetPackageName)
},
service(Type.OWNER_QUERENT_USER, "getOwnersForDomainUserId") {
// Re-use package name, since the result itself isn't relevant
getOwnersForDomain(it.targetPackageName, it.userId)

View File

@@ -147,18 +147,12 @@ class DomainVerificationSettingsMutationTest {
DomainVerificationManager.STATE_SUCCESS
)
},
service("setLinkHandlingAllowed") {
setDomainVerificationLinkHandlingAllowed(TEST_PKG, true)
},
service("setLinkHandlingAllowedUserId") {
setDomainVerificationLinkHandlingAllowed(TEST_PKG, true, TEST_USER_ID)
},
service("setLinkHandlingAllowedInternal") {
setDomainVerificationLinkHandlingAllowedInternal(TEST_PKG, true, TEST_USER_ID)
},
service("setUserSelection") {
setDomainVerificationUserSelection(TEST_UUID, setOf("example.com"), true)
},
service("setUserSelectionUserId") {
setDomainVerificationUserSelection(
TEST_UUID,

View File

@@ -16,7 +16,6 @@
package com.android.server.pm.test.verify.domain
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.parsing.component.ParsedActivity
@@ -27,7 +26,6 @@ import android.os.Build
import android.os.PatternMatcher
import android.os.Process
import android.util.ArraySet
import androidx.test.InstrumentationRegistry
import com.android.server.pm.PackageSetting
import com.android.server.pm.parsing.pkg.AndroidPackage
import com.android.server.pm.verify.domain.DomainVerificationService
@@ -41,7 +39,7 @@ import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.anyString
import java.util.UUID
class DomainVerificationManagerUserSelectionOverrideTest {
class DomainVerificationUserSelectionOverrideTest {
companion object {
private const val PKG_ONE = "com.test.one"
@@ -50,17 +48,19 @@ class DomainVerificationManagerUserSelectionOverrideTest {
private val UUID_TWO = UUID.fromString("a3389c16-7f9f-4e86-85e3-500d1249c74c")
private val DOMAIN_ONE =
DomainVerificationManagerUserSelectionOverrideTest::class.java.packageName
DomainVerificationUserSelectionOverrideTest::class.java.packageName
private const val STATE_NONE = DomainVerificationUserSelection.DOMAIN_STATE_NONE
private const val STATE_SELECTED = DomainVerificationUserSelection.DOMAIN_STATE_SELECTED
private const val STATE_VERIFIED = DomainVerificationUserSelection.DOMAIN_STATE_VERIFIED
private const val USER_ID = 0
}
private val pkg1 = mockPkgSetting(PKG_ONE, UUID_ONE)
private val pkg2 = mockPkgSetting(PKG_TWO, UUID_TWO)
fun makeManager(): DomainVerificationManager =
fun makeService() =
DomainVerificationService(mockThrowOnUnmocked {
// Assume the test has every permission necessary
whenever(enforcePermission(anyString(), anyInt(), anyInt(), anyString()))
@@ -88,7 +88,7 @@ class DomainVerificationManagerUserSelectionOverrideTest {
addPackage(pkg2)
// Starting state for all tests is to have domain 1 enabled for the first package
setDomainVerificationUserSelection(UUID_ONE, setOf(DOMAIN_ONE), true)
setDomainVerificationUserSelection(UUID_ONE, setOf(DOMAIN_ONE), true, USER_ID)
assertThat(stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_SELECTED)
}
@@ -138,37 +138,37 @@ class DomainVerificationManagerUserSelectionOverrideTest {
@Test
fun anotherPackageTakeoverSuccess() {
val manager = makeManager()
val service = makeService()
// Attempt override by package 2
manager.setDomainVerificationUserSelection(UUID_TWO, setOf(DOMAIN_ONE), true)
service.setDomainVerificationUserSelection(UUID_TWO, setOf(DOMAIN_ONE), true, USER_ID)
// 1 loses approval
assertThat(manager.stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_NONE)
assertThat(service.stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_NONE)
// 2 gains approval
assertThat(manager.stateFor(PKG_TWO, DOMAIN_ONE)).isEqualTo(STATE_SELECTED)
assertThat(service.stateFor(PKG_TWO, DOMAIN_ONE)).isEqualTo(STATE_SELECTED)
// 2 is the only owner
assertThat(manager.getOwnersForDomain(DOMAIN_ONE).map { it.packageName })
assertThat(service.getOwnersForDomain(DOMAIN_ONE, USER_ID).map { it.packageName })
.containsExactly(PKG_TWO)
}
@Test(expected = IllegalArgumentException::class)
fun anotherPackageTakeoverFailure() {
val manager = makeManager()
val service = makeService()
// Verify 1 to give it a higher approval level
manager.setDomainVerificationStatus(UUID_ONE, setOf(DOMAIN_ONE),
service.setDomainVerificationStatus(UUID_ONE, setOf(DOMAIN_ONE),
DomainVerificationManager.STATE_SUCCESS)
assertThat(manager.stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_VERIFIED)
assertThat(manager.getOwnersForDomain(DOMAIN_ONE).map { it.packageName })
assertThat(service.stateFor(PKG_ONE, DOMAIN_ONE)).isEqualTo(STATE_VERIFIED)
assertThat(service.getOwnersForDomain(DOMAIN_ONE, USER_ID).map { it.packageName })
.containsExactly(PKG_ONE)
// Attempt override by package 2
manager.setDomainVerificationUserSelection(UUID_TWO, setOf(DOMAIN_ONE), true)
service.setDomainVerificationUserSelection(UUID_TWO, setOf(DOMAIN_ONE), true, USER_ID)
}
private fun DomainVerificationManager.stateFor(pkgName: String, host: String) =
getDomainVerificationUserSelection(pkgName)!!.hostToStateMap[host]
private fun DomainVerificationService.stateFor(pkgName: String, host: String) =
getDomainVerificationUserSelection(pkgName, USER_ID)!!.hostToStateMap[host]
}