blob: a1f64f20400506a845b38fe091e87d624894ca81 [file] [log] [blame]
/*
* Copyright (C) 2014 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;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.UserHandle;
import android.util.ArraySet;
import android.util.Range;
import java.util.Collection;
import java.util.Set;
/**
* An inclusive range of UIDs.
*
* @hide
*/
public final class UidRange implements Parcelable {
public final int start;
public final int stop;
public UidRange(int startUid, int stopUid) {
if (startUid < 0) throw new IllegalArgumentException("Invalid start UID.");
if (stopUid < 0) throw new IllegalArgumentException("Invalid stop UID.");
if (startUid > stopUid) throw new IllegalArgumentException("Invalid UID range.");
start = startUid;
stop = stopUid;
}
/** Creates a UidRange for the specified user. */
public static UidRange createForUser(UserHandle user) {
final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1);
final int start = user.getUid(0 /* appId */);
final int end = nextUser.getUid(0 /* appId */) - 1;
return new UidRange(start, end);
}
/** Returns the smallest user Id which is contained in this UidRange */
public int getStartUser() {
return UserHandle.getUserHandleForUid(start).getIdentifier();
}
/** Returns the largest user Id which is contained in this UidRange */
public int getEndUser() {
return UserHandle.getUserHandleForUid(stop).getIdentifier();
}
/** Returns whether the UidRange contains the specified UID. */
public boolean contains(int uid) {
return start <= uid && uid <= stop;
}
/**
* Returns the count of UIDs in this range.
*/
public int count() {
return 1 + stop - start;
}
/**
* @return {@code true} if this range contains every UID contained by the {@code other} range.
*/
public boolean containsRange(UidRange other) {
return start <= other.start && other.stop <= stop;
}
@Override
public int hashCode() {
int result = 17;
result = 31 * result + start;
result = 31 * result + stop;
return result;
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) {
return true;
}
if (o instanceof UidRange) {
UidRange other = (UidRange) o;
return start == other.start && stop == other.stop;
}
return false;
}
@Override
public String toString() {
return start + "-" + stop;
}
// Implement the Parcelable interface
// TODO: Consider making this class no longer parcelable, since all users are likely in the
// system server.
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(start);
dest.writeInt(stop);
}
public static final @android.annotation.NonNull Creator<UidRange> CREATOR =
new Creator<UidRange>() {
@Override
public UidRange createFromParcel(Parcel in) {
int start = in.readInt();
int stop = in.readInt();
return new UidRange(start, stop);
}
@Override
public UidRange[] newArray(int size) {
return new UidRange[size];
}
};
/**
* Returns whether any of the UidRange in the collection contains the specified uid
*
* @param ranges The collection of UidRange to check
* @param uid the uid in question
* @return {@code true} if the uid is contained within the ranges, {@code false} otherwise
*
* @see UidRange#contains(int)
*/
public static boolean containsUid(Collection<UidRange> ranges, int uid) {
if (ranges == null) return false;
for (UidRange range : ranges) {
if (range.contains(uid)) {
return true;
}
}
return false;
}
/**
* Convert a set of {@code Range<Integer>} to a set of {@link UidRange}.
*/
@Nullable
public static ArraySet<UidRange> fromIntRanges(@Nullable Set<Range<Integer>> ranges) {
if (null == ranges) return null;
final ArraySet<UidRange> uids = new ArraySet<>();
for (Range<Integer> range : ranges) {
uids.add(new UidRange(range.getLower(), range.getUpper()));
}
return uids;
}
/**
* Convert a set of {@link UidRange} to a set of {@code Range<Integer>}.
*/
@Nullable
public static ArraySet<Range<Integer>> toIntRanges(@Nullable Set<UidRange> ranges) {
if (null == ranges) return null;
final ArraySet<Range<Integer>> uids = new ArraySet<>();
for (UidRange range : ranges) {
uids.add(new Range<Integer>(range.start, range.stop));
}
return uids;
}
/**
* Compare if the given UID range sets have the same UIDs.
*
* @hide
*/
public static boolean hasSameUids(@Nullable Set<UidRange> uids1,
@Nullable Set<UidRange> uids2) {
if (null == uids1) return null == uids2;
if (null == uids2) return false;
// Make a copy so it can be mutated to check that all ranges in uids2 also are in uids.
final Set<UidRange> remainingUids = new ArraySet<>(uids2);
for (UidRange range : uids1) {
if (!remainingUids.contains(range)) {
return false;
}
remainingUids.remove(range);
}
return remainingUids.isEmpty();
}
}