• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 
17 package com.android.server;
18 
19 import android.annotation.NonNull;
20 import android.net.ConnectivityManager;
21 import android.net.ConnectivityManager.NetworkCallback;
22 
23 import com.android.net.module.util.GrowingIntArray;
24 
25 /**
26  * A utility class to add/remove {@link NetworkCallback}s from a queue.
27  *
28  * <p>This is intended to be used as a temporary builder to create/modify callbacks stored in an int
29  * array for memory efficiency.
30  *
31  * <p>Intended usage:
32  * <pre>
33  *     final CallbackQueue queue = new CallbackQueue(storedCallbacks);
34  *     queue.forEach(netId, callbackId -> { [...] });
35  *     queue.addCallback(netId, callbackId);
36  *     [...]
37  *     storedCallbacks = queue.getMinimizedBackingArray();
38  * </pre>
39  *
40  * <p>This class is not thread-safe.
41  */
42 public class CallbackQueue extends GrowingIntArray {
CallbackQueue(int[] initialCallbacks)43     public CallbackQueue(int[] initialCallbacks) {
44         super(initialCallbacks);
45     }
46 
47     /**
48      * Get a callback int from netId and callbackId.
49      *
50      * <p>The first 16 bits of each int is the netId; the last 16 bits are the callback index.
51      */
getCallbackInt(int netId, int callbackId)52     private static int getCallbackInt(int netId, int callbackId) {
53         return (netId << 16) | (callbackId & 0xffff);
54     }
55 
getNetId(int callbackInt)56     private static int getNetId(int callbackInt) {
57         return callbackInt >>> 16;
58     }
59 
getCallbackId(int callbackInt)60     private static int getCallbackId(int callbackInt) {
61         return callbackInt & 0xffff;
62     }
63 
64     /**
65      * A consumer interface for {@link #forEach(CallbackConsumer)}.
66      *
67      * <p>This is similar to a BiConsumer&lt;Integer, Integer&gt;, but avoids the boxing cost.
68      */
69     public interface CallbackConsumer {
70         /**
71          * Method called on each callback in the queue.
72          */
accept(int netId, int callbackId)73         void accept(int netId, int callbackId);
74     }
75 
76     /**
77      * Iterate over all callbacks in the queue.
78      */
forEach(@onNull CallbackConsumer consumer)79     public void forEach(@NonNull CallbackConsumer consumer) {
80         forEach(value -> {
81             final int netId = getNetId(value);
82             final int callbackId = getCallbackId(value);
83             consumer.accept(netId, callbackId);
84         });
85     }
86 
87     /**
88      * Indicates whether the queue contains a callback for the given (netId, callbackId).
89      */
hasCallback(int netId, int callbackId)90     public boolean hasCallback(int netId, int callbackId) {
91         return contains(getCallbackInt(netId, callbackId));
92     }
93 
94     /**
95      * Remove all callbacks for the given netId.
96      *
97      * @return true if at least one callback was removed.
98      */
removeCallbacksForNetId(int netId)99     public boolean removeCallbacksForNetId(int netId) {
100         return removeValues(cb -> getNetId(cb) == netId);
101     }
102 
103     /**
104      * Remove all callbacks for the given netId and callbackId.
105      * @return true if at least one callback was removed.
106      */
removeCallbacks(int netId, int callbackId)107     public boolean removeCallbacks(int netId, int callbackId) {
108         final int cbInt = getCallbackInt(netId, callbackId);
109         return removeValues(cb -> cb == cbInt);
110     }
111 
112     /**
113      * Add a callback at the end of the queue.
114      */
addCallback(int netId, int callbackId)115     public void addCallback(int netId, int callbackId) {
116         add(getCallbackInt(netId, callbackId));
117     }
118 
119     @Override
valueToString(int item)120     protected String valueToString(int item) {
121         final int callbackId = getCallbackId(item);
122         final int netId = getNetId(item);
123         return ConnectivityManager.getCallbackName(callbackId) + "(" + netId + ")";
124     }
125 }
126