/*
 * Copyright (C) 2018 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.net.wifi;

import static com.android.internal.util.Preconditions.checkNotNull;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
import android.net.MacAddress;
import android.net.MatchAllNetworkSpecifier;
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.PatternMatcher;
import android.os.Process;
import android.text.TextUtils;
import android.util.Pair;

import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * Network specifier object used to request a local Wi-Fi network. Apps should use the
 * {@link WifiNetworkSpecifier.Builder} class to create an instance.
 */
public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parcelable {

    /**
     * Builder used to create {@link WifiNetworkSpecifier} objects.
     */
    public static final class Builder {
        private static final String MATCH_ALL_SSID_PATTERN_PATH = ".*";
        private static final String MATCH_EMPTY_SSID_PATTERN_PATH = "";
        private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN1 =
                new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS);
        private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN2 =
                new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.BROADCAST_ADDRESS);
        private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN =
                new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS);
        private static final MacAddress MATCH_EXACT_BSSID_PATTERN_MASK =
                MacAddress.BROADCAST_ADDRESS;

        /**
         * SSID pattern match specified by the app.
         */
        private @Nullable PatternMatcher mSsidPatternMatcher;
        /**
         * BSSID pattern match specified by the app.
         * Pair of <BaseAddress, Mask>.
         */
        private @Nullable Pair<MacAddress, MacAddress> mBssidPatternMatcher;
        /**
         * Whether this is an OWE network or not.
         */
        private boolean mIsEnhancedOpen;
        /**
         * Pre-shared key for use with WPA-PSK networks.
         */
        private @Nullable String mWpa2PskPassphrase;
        /**
         * Pre-shared key for use with WPA3-SAE networks.
         */
        private @Nullable String mWpa3SaePassphrase;
        /**
         * The enterprise configuration details specifying the EAP method,
         * certificates and other settings associated with the WPA-EAP networks.
         */
        private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
        /**
         * The enterprise configuration details specifying the EAP method,
         * certificates and other settings associated with the SuiteB networks.
         */
        private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
        /**
         * This is a network that does not broadcast its SSID, so an
         * SSID-specific probe request must be used for scans.
         */
        private boolean mIsHiddenSSID;

        public Builder() {
            mSsidPatternMatcher = null;
            mBssidPatternMatcher = null;
            mIsEnhancedOpen = false;
            mWpa2PskPassphrase = null;
            mWpa3SaePassphrase = null;
            mWpa2EnterpriseConfig = null;
            mWpa3EnterpriseConfig = null;
            mIsHiddenSSID = false;
        }

        /**
         * Set the unicode SSID match pattern to use for filtering networks from scan results.
         * <p>
         * <li>Overrides any previous value set using {@link #setSsid(String)} or
         * {@link #setSsidPattern(PatternMatcher)}.</li>
         *
         * @param ssidPattern Instance of {@link PatternMatcher} containing the UTF-8 encoded
         *                    string pattern to use for matching the network's SSID.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         */
        public @NonNull Builder setSsidPattern(@NonNull PatternMatcher ssidPattern) {
            checkNotNull(ssidPattern);
            mSsidPatternMatcher = ssidPattern;
            return this;
        }

        /**
         * Set the unicode SSID for the network.
         * <p>
         * <li>Sets the SSID to use for filtering networks from scan results. Will only match
         * networks whose SSID is identical to the UTF-8 encoding of the specified value.</li>
         * <li>Overrides any previous value set using {@link #setSsid(String)} or
         * {@link #setSsidPattern(PatternMatcher)}.</li>
         *
         * @param ssid The SSID of the network. It must be valid Unicode.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         * @throws IllegalArgumentException if the SSID is not valid unicode.
         */
        public @NonNull Builder setSsid(@NonNull String ssid) {
            checkNotNull(ssid);
            final CharsetEncoder unicodeEncoder = StandardCharsets.UTF_8.newEncoder();
            if (!unicodeEncoder.canEncode(ssid)) {
                throw new IllegalArgumentException("SSID is not a valid unicode string");
            }
            mSsidPatternMatcher = new PatternMatcher(ssid, PatternMatcher.PATTERN_LITERAL);
            return this;
        }

        /**
         * Set the BSSID match pattern to use for filtering networks from scan results.
         * Will match all networks with BSSID which satisfies the following:
         * {@code BSSID & mask == baseAddress}.
         * <p>
         * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
         * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
         *
         * @param baseAddress Base address for BSSID pattern.
         * @param mask Mask for BSSID pattern.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         */
        public @NonNull Builder setBssidPattern(
                @NonNull MacAddress baseAddress, @NonNull MacAddress mask) {
            checkNotNull(baseAddress, mask);
            mBssidPatternMatcher = Pair.create(baseAddress, mask);
            return this;
        }

        /**
         * Set the BSSID to use for filtering networks from scan results. Will only match network
         * whose BSSID is identical to the specified value.
         * <p>
         * <li>Sets the BSSID to use for filtering networks from scan results. Will only match
         * networks whose BSSID is identical to specified value.</li>
         * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or
         * {@link #setBssidPattern(MacAddress, MacAddress)}.</li>
         *
         * @param bssid BSSID of the network.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         */
        public @NonNull Builder setBssid(@NonNull MacAddress bssid) {
            checkNotNull(bssid);
            mBssidPatternMatcher = Pair.create(bssid, MATCH_EXACT_BSSID_PATTERN_MASK);
            return this;
        }

        /**
         * Specifies whether this represents an Enhanced Open (OWE) network.
         *
         * @param isEnhancedOpen {@code true} to indicate that the network uses enhanced open,
         *                       {@code false} otherwise.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         */
        public @NonNull Builder setIsEnhancedOpen(boolean isEnhancedOpen) {
            mIsEnhancedOpen = isEnhancedOpen;
            return this;
        }

        /**
         * Set the ASCII WPA2 passphrase for this network. Needed for authenticating to
         * WPA2-PSK networks.
         *
         * @param passphrase passphrase of the network.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
         */
        public @NonNull Builder setWpa2Passphrase(@NonNull String passphrase) {
            checkNotNull(passphrase);
            final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
            if (!asciiEncoder.canEncode(passphrase)) {
                throw new IllegalArgumentException("passphrase not ASCII encodable");
            }
            mWpa2PskPassphrase = passphrase;
            return this;
        }

        /**
         * Set the ASCII WPA3 passphrase for this network. Needed for authenticating to WPA3-SAE
         * networks.
         *
         * @param passphrase passphrase of the network.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         * @throws IllegalArgumentException if the passphrase is not ASCII encodable.
         */
        public @NonNull Builder setWpa3Passphrase(@NonNull String passphrase) {
            checkNotNull(passphrase);
            final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder();
            if (!asciiEncoder.canEncode(passphrase)) {
                throw new IllegalArgumentException("passphrase not ASCII encodable");
            }
            mWpa3SaePassphrase = passphrase;
            return this;
        }

        /**
         * Set the associated enterprise configuration for this network. Needed for authenticating
         * to WPA2-EAP networks. See {@link WifiEnterpriseConfig} for description.
         *
         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         */
        public @NonNull Builder setWpa2EnterpriseConfig(
                @NonNull WifiEnterpriseConfig enterpriseConfig) {
            checkNotNull(enterpriseConfig);
            mWpa2EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
            return this;
        }

        /**
         * Set the associated enterprise configuration for this network. Needed for authenticating
         * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
         *
         * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         */
        public @NonNull Builder setWpa3EnterpriseConfig(
                @NonNull WifiEnterpriseConfig enterpriseConfig) {
            checkNotNull(enterpriseConfig);
            mWpa3EnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig);
            return this;
        }

        /**
         * Specifies whether this represents a hidden network.
         * <p>
         * <li>Setting this disallows the usage of {@link #setSsidPattern(PatternMatcher)} since
         * hidden networks need to be explicitly probed for.</li>
         * <li>If not set, defaults to false (i.e not a hidden network).</li>
         *
         * @param isHiddenSsid {@code true} to indicate that the network is hidden, {@code false}
         *                     otherwise.
         * @return Instance of {@link Builder} to enable chaining of the builder method.
         */
        public @NonNull Builder setIsHiddenSsid(boolean isHiddenSsid) {
            mIsHiddenSSID = isHiddenSsid;
            return this;
        }

        private void setSecurityParamsInWifiConfiguration(
                @NonNull WifiConfiguration configuration) {
            if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
                // WifiConfiguration.preSharedKey needs quotes around ASCII password.
                configuration.preSharedKey = "\"" + mWpa2PskPassphrase + "\"";
            } else if (!TextUtils.isEmpty(mWpa3SaePassphrase)) { // WPA3-SAE network.
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_SAE);
                // WifiConfiguration.preSharedKey needs quotes around ASCII password.
                configuration.preSharedKey = "\"" + mWpa3SaePassphrase + "\"";
            } else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
                configuration.enterpriseConfig = mWpa2EnterpriseConfig;
            } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
                configuration.enterpriseConfig = mWpa3EnterpriseConfig;
            } else if (mIsEnhancedOpen) { // OWE network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
            } else { // Open network
                configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
            }
        }

        /**
         * Helper method to build WifiConfiguration object from the builder.
         * @return Instance of {@link WifiConfiguration}.
         */
        private WifiConfiguration buildWifiConfiguration() {
            final WifiConfiguration wifiConfiguration = new WifiConfiguration();
            // WifiConfiguration.SSID needs quotes around unicode SSID.
            if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) {
                wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\"";
            }
            if (mBssidPatternMatcher.second == MATCH_EXACT_BSSID_PATTERN_MASK) {
                wifiConfiguration.BSSID = mBssidPatternMatcher.first.toString();
            }
            setSecurityParamsInWifiConfiguration(wifiConfiguration);
            wifiConfiguration.hiddenSSID = mIsHiddenSSID;
            return wifiConfiguration;
        }

        private boolean hasSetAnyPattern() {
            return mSsidPatternMatcher != null || mBssidPatternMatcher != null;
        }

        private void setMatchAnyPatternIfUnset() {
            if (mSsidPatternMatcher == null) {
                mSsidPatternMatcher = new PatternMatcher(MATCH_ALL_SSID_PATTERN_PATH,
                        PatternMatcher.PATTERN_SIMPLE_GLOB);
            }
            if (mBssidPatternMatcher == null) {
                mBssidPatternMatcher = MATCH_ALL_BSSID_PATTERN;
            }
        }

        private boolean hasSetMatchNonePattern() {
            if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_PREFIX
                    && mSsidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) {
                return true;
            }
            if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN1)) {
                return true;
            }
            if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN2)) {
                return true;
            }
            return false;
        }

        private boolean hasSetMatchAllPattern() {
            if ((mSsidPatternMatcher.match(MATCH_EMPTY_SSID_PATTERN_PATH))
                    && mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)) {
                return true;
            }
            return false;
        }

        private void validateSecurityParams() {
            int numSecurityTypes = 0;
            numSecurityTypes += mIsEnhancedOpen ? 1 : 0;
            numSecurityTypes += !TextUtils.isEmpty(mWpa2PskPassphrase) ? 1 : 0;
            numSecurityTypes += !TextUtils.isEmpty(mWpa3SaePassphrase) ? 1 : 0;
            numSecurityTypes += mWpa2EnterpriseConfig != null ? 1 : 0;
            numSecurityTypes += mWpa3EnterpriseConfig != null ? 1 : 0;
            if (numSecurityTypes > 1) {
                throw new IllegalStateException("only one of setIsEnhancedOpen, setWpa2Passphrase,"
                        + "setWpa3Passphrase, setWpa2EnterpriseConfig or setWpa3EnterpriseConfig"
                        + " can be invoked for network specifier");
            }
        }

        /**
         * Create a specifier object used to request a local Wi-Fi network. The generated
         * {@link NetworkSpecifier} should be used in
         * {@link NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} when building
         * the {@link NetworkRequest}. These specifiers can only be used to request a local wifi
         * network (i.e no internet capability). So, the device will not switch it's default route
         * to wifi if there are other transports (cellular for example) available.
         *<p>
         * Note: Apps can set a combination of network match params:
         * <li> SSID Pattern using {@link #setSsidPattern(PatternMatcher)} OR Specific SSID using
         * {@link #setSsid(String)}. </li>
         * AND/OR
         * <li> BSSID Pattern using {@link #setBssidPattern(MacAddress, MacAddress)} OR Specific
         * BSSID using {@link #setBssid(MacAddress)} </li>
         * to trigger connection to a network that matches the set params.
         * The system will find the set of networks matching the request and present the user
         * with a system dialog which will allow the user to select a specific Wi-Fi network to
         * connect to or to deny the request.
         *</p>
         *
         * For example:
         * To connect to an open network with a SSID prefix of "test" and a BSSID OUI of "10:03:23":
         * {@code
         * final NetworkSpecifier specifier =
         *      new Builder()
         *      .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX))
         *      .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"),
         *                       MacAddress.fromString("ff:ff:ff:00:00:00"))
         *      .build()
         * final NetworkRequest request =
         *      new NetworkRequest.Builder()
         *      .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
         *      .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
         *      .setNetworkSpecifier(specifier)
         *      .build();
         * final ConnectivityManager connectivityManager =
         *      context.getSystemService(Context.CONNECTIVITY_SERVICE);
         * final NetworkCallback networkCallback = new NetworkCallback() {
         *      ...
         *      {@literal @}Override
         *      void onAvailable(...) {}
         *      // etc.
         * };
         * connectivityManager.requestNetwork(request, networkCallback);
         * }
         *
         * @return Instance of {@link NetworkSpecifier}.
         * @throws IllegalStateException on invalid params set.
         */
        public @NonNull WifiNetworkSpecifier build() {
            if (!hasSetAnyPattern()) {
                throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/"
                        + "setBssid should be invoked for specifier");
            }
            setMatchAnyPatternIfUnset();
            if (hasSetMatchNonePattern()) {
                throw new IllegalStateException("cannot set match-none pattern for specifier");
            }
            if (hasSetMatchAllPattern()) {
                throw new IllegalStateException("cannot set match-all pattern for specifier");
            }
            if (mIsHiddenSSID && mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL) {
                throw new IllegalStateException("setSsid should also be invoked when "
                        + "setIsHiddenSsid is invoked for network specifier");
            }
            validateSecurityParams();

            return new WifiNetworkSpecifier(
                    mSsidPatternMatcher,
                    mBssidPatternMatcher,
                    buildWifiConfiguration(),
                    Process.myUid(),
                    ActivityThread.currentApplication().getApplicationContext().getOpPackageName());
        }
    }

    /**
     * SSID pattern match specified by the app.
     * @hide
     */
    public final PatternMatcher ssidPatternMatcher;

    /**
     * BSSID pattern match specified by the app.
     * Pair of <BaseAddress, Mask>.
     * @hide
     */
    public final Pair<MacAddress, MacAddress> bssidPatternMatcher;

    /**
     * Security credentials for the network.
     * <p>
     * Note: {@link WifiConfiguration#SSID} & {@link WifiConfiguration#BSSID} fields from
     * WifiConfiguration are not used. Instead we use the {@link #ssidPatternMatcher} &
     * {@link #bssidPatternMatcher} fields embedded directly
     * within {@link WifiNetworkSpecifier}.
     * @hide
     */
    public final WifiConfiguration wifiConfiguration;

    /**
     * The UID of the process initializing this network specifier. Validated by receiver using
     * checkUidIfNecessary() and is used by satisfiedBy() to determine whether the specifier
     * matches the offered network.
     * @hide
     */
    public final int requestorUid;

    /**
     * The package name of the app initializing this network specifier.
     * @hide
     */
    public final String requestorPackageName;

    /** @hide */
    public WifiNetworkSpecifier() throws IllegalAccessException {
        throw new IllegalAccessException("Use the builder to create an instance");
    }

    /** @hide */
    public WifiNetworkSpecifier(@NonNull PatternMatcher ssidPatternMatcher,
                                @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher,
                                @NonNull WifiConfiguration wifiConfiguration,
                                int requestorUid, @NonNull String requestorPackageName) {
        checkNotNull(ssidPatternMatcher);
        checkNotNull(bssidPatternMatcher);
        checkNotNull(wifiConfiguration);
        checkNotNull(requestorPackageName);

        this.ssidPatternMatcher = ssidPatternMatcher;
        this.bssidPatternMatcher = bssidPatternMatcher;
        this.wifiConfiguration = wifiConfiguration;
        this.requestorUid = requestorUid;
        this.requestorPackageName = requestorPackageName;
    }

    public static final @NonNull Creator<WifiNetworkSpecifier> CREATOR =
            new Creator<WifiNetworkSpecifier>() {
                @Override
                public WifiNetworkSpecifier createFromParcel(Parcel in) {
                    PatternMatcher ssidPatternMatcher = in.readParcelable(/* classLoader */null);
                    MacAddress baseAddress = in.readParcelable(null);
                    MacAddress mask = in.readParcelable(null);
                    Pair<MacAddress, MacAddress> bssidPatternMatcher =
                            Pair.create(baseAddress, mask);
                    WifiConfiguration wifiConfiguration = in.readParcelable(null);
                    int requestorUid = in.readInt();
                    String requestorPackageName = in.readString();
                    return new WifiNetworkSpecifier(ssidPatternMatcher, bssidPatternMatcher,
                            wifiConfiguration, requestorUid, requestorPackageName);
                }

                @Override
                public WifiNetworkSpecifier[] newArray(int size) {
                    return new WifiNetworkSpecifier[size];
                }
            };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeParcelable(ssidPatternMatcher, flags);
        dest.writeParcelable(bssidPatternMatcher.first, flags);
        dest.writeParcelable(bssidPatternMatcher.second, flags);
        dest.writeParcelable(wifiConfiguration, flags);
        dest.writeInt(requestorUid);
        dest.writeString(requestorPackageName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(
                ssidPatternMatcher.getPath(),
                ssidPatternMatcher.getType(),
                bssidPatternMatcher,
                wifiConfiguration.allowedKeyManagement,
                requestorUid, requestorPackageName);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof WifiNetworkSpecifier)) {
            return false;
        }
        WifiNetworkSpecifier lhs = (WifiNetworkSpecifier) obj;
        return Objects.equals(this.ssidPatternMatcher.getPath(),
                    lhs.ssidPatternMatcher.getPath())
                && Objects.equals(this.ssidPatternMatcher.getType(),
                    lhs.ssidPatternMatcher.getType())
                && Objects.equals(this.bssidPatternMatcher,
                    lhs.bssidPatternMatcher)
                && Objects.equals(this.wifiConfiguration.allowedKeyManagement,
                    lhs.wifiConfiguration.allowedKeyManagement)
                && requestorUid == lhs.requestorUid
                && TextUtils.equals(requestorPackageName, lhs.requestorPackageName);
    }

    @Override
    public String toString() {
        return new StringBuilder()
                .append("WifiNetworkSpecifier [")
                .append(", SSID Match pattern=").append(ssidPatternMatcher)
                .append(", BSSID Match pattern=").append(bssidPatternMatcher)
                .append(", SSID=").append(wifiConfiguration.SSID)
                .append(", BSSID=").append(wifiConfiguration.BSSID)
                .append(", requestorUid=").append(requestorUid)
                .append(", requestorPackageName=").append(requestorPackageName)
                .append("]")
                .toString();
    }

    /** @hide */
    @Override
    public boolean satisfiedBy(NetworkSpecifier other) {
        if (this == other) {
            return true;
        }
        // Any generic requests should be satisifed by a specific wifi network.
        if (other == null || other instanceof MatchAllNetworkSpecifier) {
            return true;
        }
        if (other instanceof WifiNetworkAgentSpecifier) {
            return ((WifiNetworkAgentSpecifier) other).satisfiesNetworkSpecifier(this);
        }
        // Specific requests are checked for equality although testing for equality of 2 patterns do
        // not make much sense!
        return equals(other);
    }

    /** @hide */
    @Override
    public void assertValidFromUid(int requestorUid) {
        if (this.requestorUid != requestorUid) {
            throw new SecurityException("mismatched UIDs");
        }
    }
}
