1 /* 2 * Copyright (C) 2020 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 android.net; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.telephony.data.EpsBearerQosSessionAttributes; 22 import android.telephony.data.NrQosSessionAttributes; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 26 import java.util.Objects; 27 import java.util.concurrent.Executor; 28 29 /** 30 * Sends messages from {@link com.android.server.ConnectivityService} to the registered 31 * {@link QosCallback}. 32 * <p/> 33 * This is a satellite class of {@link ConnectivityManager} and not meant 34 * to be used in other contexts. 35 * 36 * @hide 37 */ 38 class QosCallbackConnection extends android.net.IQosCallback.Stub { 39 40 @NonNull private final ConnectivityManager mConnectivityManager; 41 @Nullable private volatile QosCallback mCallback; 42 @NonNull private final Executor mExecutor; 43 44 @VisibleForTesting 45 @Nullable getCallback()46 public QosCallback getCallback() { 47 return mCallback; 48 } 49 50 /** 51 * The constructor for the connection 52 * 53 * @param connectivityManager the mgr that created this connection 54 * @param callback the callback to send messages back to 55 * @param executor The executor on which the callback will be invoked. The provided 56 * {@link Executor} must run callback sequentially, otherwise the order of 57 * callbacks cannot be guaranteed. 58 */ QosCallbackConnection(@onNull final ConnectivityManager connectivityManager, @NonNull final QosCallback callback, @NonNull final Executor executor)59 QosCallbackConnection(@NonNull final ConnectivityManager connectivityManager, 60 @NonNull final QosCallback callback, 61 @NonNull final Executor executor) { 62 mConnectivityManager = Objects.requireNonNull(connectivityManager, 63 "connectivityManager must be non-null"); 64 mCallback = Objects.requireNonNull(callback, "callback must be non-null"); 65 mExecutor = Objects.requireNonNull(executor, "executor must be non-null"); 66 } 67 68 /** 69 * Called when either the {@link EpsBearerQosSessionAttributes} has changed or on the first time 70 * the attributes have become available. 71 * 72 * @param session the session that is now available 73 * @param attributes the corresponding attributes of session 74 */ 75 @Override onQosEpsBearerSessionAvailable(@onNull final QosSession session, @NonNull final EpsBearerQosSessionAttributes attributes)76 public void onQosEpsBearerSessionAvailable(@NonNull final QosSession session, 77 @NonNull final EpsBearerQosSessionAttributes attributes) { 78 79 mExecutor.execute(() -> { 80 final QosCallback callback = mCallback; 81 if (callback != null) { 82 callback.onQosSessionAvailable(session, attributes); 83 } 84 }); 85 } 86 87 /** 88 * Called when either the {@link NrQosSessionAttributes} has changed or on the first time 89 * the attributes have become available. 90 * 91 * @param session the session that is now available 92 * @param attributes the corresponding attributes of session 93 */ 94 @Override onNrQosSessionAvailable(@onNull final QosSession session, @NonNull final NrQosSessionAttributes attributes)95 public void onNrQosSessionAvailable(@NonNull final QosSession session, 96 @NonNull final NrQosSessionAttributes attributes) { 97 98 mExecutor.execute(() -> { 99 final QosCallback callback = mCallback; 100 if (callback != null) { 101 callback.onQosSessionAvailable(session, attributes); 102 } 103 }); 104 } 105 106 /** 107 * Called when the session is lost. 108 * 109 * @param session the session that was lost 110 */ 111 @Override onQosSessionLost(@onNull final QosSession session)112 public void onQosSessionLost(@NonNull final QosSession session) { 113 mExecutor.execute(() -> { 114 final QosCallback callback = mCallback; 115 if (callback != null) { 116 callback.onQosSessionLost(session); 117 } 118 }); 119 } 120 121 /** 122 * Called when there is an error on the registered callback. 123 * 124 * @param errorType the type of error 125 */ 126 @Override onError(@osCallbackException.ExceptionType final int errorType)127 public void onError(@QosCallbackException.ExceptionType final int errorType) { 128 mExecutor.execute(() -> { 129 final QosCallback callback = mCallback; 130 if (callback != null) { 131 // Messages no longer need to be received since there was an error. 132 stopReceivingMessages(); 133 mConnectivityManager.unregisterQosCallback(callback); 134 callback.onError(QosCallbackException.createException(errorType)); 135 } 136 }); 137 } 138 139 /** 140 * The callback will stop receiving messages. 141 * <p/> 142 * There are no synchronization guarantees on exactly when the callback will stop receiving 143 * messages. 144 */ stopReceivingMessages()145 void stopReceivingMessages() { 146 mCallback = null; 147 } 148 } 149