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:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
*/
|
||||
/*
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
Reference in New Issue
Block a user