blob: a1f64f20400506a845b38fe091e87d624894ca81 [file] [log] [blame]
Paul Jensen8b5fc622014-05-07 15:27:40 -04001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net;
18
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -070019import android.annotation.Nullable;
Paul Jensen8b5fc622014-05-07 15:27:40 -040020import android.os.Parcel;
Lorenzo Colitti86b51bb2019-03-18 23:50:34 +090021import android.os.Parcelable;
Lorenzo Colitti8876a3d2021-02-16 15:42:21 +090022import android.os.UserHandle;
Chiachang Wang8156c4e2021-03-19 00:45:39 +000023import android.util.ArraySet;
24import android.util.Range;
Paul Jensen8b5fc622014-05-07 15:27:40 -040025
Lorenzo Colittibad9d912019-04-12 10:48:06 +000026import java.util.Collection;
Chiachang Wang8156c4e2021-03-19 00:45:39 +000027import java.util.Set;
Lorenzo Colittibad9d912019-04-12 10:48:06 +000028
Paul Jensen8b5fc622014-05-07 15:27:40 -040029/**
30 * An inclusive range of UIDs.
31 *
32 * @hide
33 */
Lorenzo Colitti86b51bb2019-03-18 23:50:34 +090034public final class UidRange implements Parcelable {
35 public final int start;
36 public final int stop;
37
Paul Jensen8b5fc622014-05-07 15:27:40 -040038 public UidRange(int startUid, int stopUid) {
39 if (startUid < 0) throw new IllegalArgumentException("Invalid start UID.");
40 if (stopUid < 0) throw new IllegalArgumentException("Invalid stop UID.");
41 if (startUid > stopUid) throw new IllegalArgumentException("Invalid UID range.");
42 start = startUid;
43 stop = stopUid;
44 }
45
Lorenzo Colitti8876a3d2021-02-16 15:42:21 +090046 /** Creates a UidRange for the specified user. */
47 public static UidRange createForUser(UserHandle user) {
48 final UserHandle nextUser = UserHandle.of(user.getIdentifier() + 1);
Chiachang Wang612cc032021-04-08 11:10:51 +080049 final int start = user.getUid(0 /* appId */);
50 final int end = nextUser.getUid(0 /* appId */) - 1;
Lorenzo Colitti8876a3d2021-02-16 15:42:21 +090051 return new UidRange(start, end);
52 }
53
Lorenzo Colittibad9d912019-04-12 10:48:06 +000054 /** Returns the smallest user Id which is contained in this UidRange */
Paul Jensen8b5fc622014-05-07 15:27:40 -040055 public int getStartUser() {
lucaslin19a48b82021-02-19 18:21:02 +080056 return UserHandle.getUserHandleForUid(start).getIdentifier();
Paul Jensen8b5fc622014-05-07 15:27:40 -040057 }
58
Lorenzo Colittibad9d912019-04-12 10:48:06 +000059 /** Returns the largest user Id which is contained in this UidRange */
60 public int getEndUser() {
lucaslin19a48b82021-02-19 18:21:02 +080061 return UserHandle.getUserHandleForUid(stop).getIdentifier();
Lorenzo Colittibad9d912019-04-12 10:48:06 +000062 }
63
Remi NGUYEN VANb2eabd42021-03-02 12:12:49 +090064 /** Returns whether the UidRange contains the specified UID. */
Robin Lee722ee0b2016-05-09 12:32:27 +010065 public boolean contains(int uid) {
66 return start <= uid && uid <= stop;
67 }
68
69 /**
Chalard Jean4409dfa2018-02-26 19:00:45 +090070 * Returns the count of UIDs in this range.
71 */
72 public int count() {
73 return 1 + stop - start;
74 }
75
76 /**
Remi NGUYEN VANb2eabd42021-03-02 12:12:49 +090077 * @return {@code true} if this range contains every UID contained by the {@code other} range.
Robin Lee722ee0b2016-05-09 12:32:27 +010078 */
79 public boolean containsRange(UidRange other) {
80 return start <= other.start && other.stop <= stop;
81 }
82
Paul Jensen8b5fc622014-05-07 15:27:40 -040083 @Override
84 public int hashCode() {
85 int result = 17;
86 result = 31 * result + start;
87 result = 31 * result + stop;
88 return result;
89 }
90
91 @Override
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -070092 public boolean equals(@Nullable Object o) {
Paul Jensen8b5fc622014-05-07 15:27:40 -040093 if (this == o) {
94 return true;
95 }
96 if (o instanceof UidRange) {
97 UidRange other = (UidRange) o;
98 return start == other.start && stop == other.stop;
99 }
100 return false;
101 }
102
103 @Override
104 public String toString() {
105 return start + "-" + stop;
106 }
107
Lorenzo Colitti86b51bb2019-03-18 23:50:34 +0900108 // Implement the Parcelable interface
109 // TODO: Consider making this class no longer parcelable, since all users are likely in the
110 // system server.
111 @Override
112 public int describeContents() {
113 return 0;
114 }
115
116 @Override
117 public void writeToParcel(Parcel dest, int flags) {
118 dest.writeInt(start);
119 dest.writeInt(stop);
120 }
Paul Jensen8b5fc622014-05-07 15:27:40 -0400121
Jeff Sharkeyf8525282019-02-28 12:06:45 -0700122 public static final @android.annotation.NonNull Creator<UidRange> CREATOR =
Remi NGUYEN VANb2eabd42021-03-02 12:12:49 +0900123 new Creator<UidRange>() {
124 @Override
125 public UidRange createFromParcel(Parcel in) {
126 int start = in.readInt();
127 int stop = in.readInt();
Lorenzo Colitti86b51bb2019-03-18 23:50:34 +0900128
Remi NGUYEN VANb2eabd42021-03-02 12:12:49 +0900129 return new UidRange(start, stop);
130 }
131 @Override
132 public UidRange[] newArray(int size) {
133 return new UidRange[size];
134 }
Paul Jensen8b5fc622014-05-07 15:27:40 -0400135 };
Lorenzo Colittibad9d912019-04-12 10:48:06 +0000136
137 /**
138 * Returns whether any of the UidRange in the collection contains the specified uid
139 *
140 * @param ranges The collection of UidRange to check
141 * @param uid the uid in question
142 * @return {@code true} if the uid is contained within the ranges, {@code false} otherwise
143 *
144 * @see UidRange#contains(int)
145 */
146 public static boolean containsUid(Collection<UidRange> ranges, int uid) {
147 if (ranges == null) return false;
148 for (UidRange range : ranges) {
149 if (range.contains(uid)) {
150 return true;
151 }
152 }
153 return false;
154 }
Chiachang Wang8156c4e2021-03-19 00:45:39 +0000155
156 /**
157 * Convert a set of {@code Range<Integer>} to a set of {@link UidRange}.
158 */
159 @Nullable
160 public static ArraySet<UidRange> fromIntRanges(@Nullable Set<Range<Integer>> ranges) {
161 if (null == ranges) return null;
162
163 final ArraySet<UidRange> uids = new ArraySet<>();
164 for (Range<Integer> range : ranges) {
165 uids.add(new UidRange(range.getLower(), range.getUpper()));
166 }
167 return uids;
168 }
169
170 /**
171 * Convert a set of {@link UidRange} to a set of {@code Range<Integer>}.
172 */
173 @Nullable
174 public static ArraySet<Range<Integer>> toIntRanges(@Nullable Set<UidRange> ranges) {
175 if (null == ranges) return null;
176
177 final ArraySet<Range<Integer>> uids = new ArraySet<>();
178 for (UidRange range : ranges) {
179 uids.add(new Range<Integer>(range.start, range.stop));
180 }
181 return uids;
182 }
Chalard Jeanf4802fa2021-12-13 21:37:12 +0900183
184 /**
185 * Compare if the given UID range sets have the same UIDs.
186 *
187 * @hide
188 */
189 public static boolean hasSameUids(@Nullable Set<UidRange> uids1,
190 @Nullable Set<UidRange> uids2) {
191 if (null == uids1) return null == uids2;
192 if (null == uids2) return false;
193 // Make a copy so it can be mutated to check that all ranges in uids2 also are in uids.
194 final Set<UidRange> remainingUids = new ArraySet<>(uids2);
195 for (UidRange range : uids1) {
196 if (!remainingUids.contains(range)) {
197 return false;
198 }
199 remainingUids.remove(range);
200 }
201 return remainingUids.isEmpty();
202 }
Paul Jensen8b5fc622014-05-07 15:27:40 -0400203}