Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a4df7f5 authored by Winson's avatar Winson
Browse files

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
parent c28d1fee
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);
+1 −2
Original line number Diff line number Diff line
@@ -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);
                    }
                });

+165 −22
Original line number Diff line number Diff line
@@ -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;
+0 −202
Original line number Diff line number Diff line
/*
 * 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;
        }
    }
}
+26 −13

File changed.

Preview size limit exceeded, changes collapsed.

Loading