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 com.android.server.connectivity; 18 19 import static android.net.QosCallbackException.EX_TYPE_FILTER_NONE; 20 21 import android.annotation.NonNull; 22 import android.net.IQosCallback; 23 import android.net.Network; 24 import android.net.QosCallbackException; 25 import android.net.QosFilter; 26 import android.net.QosSession; 27 import android.os.IBinder; 28 import android.os.RemoteException; 29 import android.telephony.data.EpsBearerQosSessionAttributes; 30 import android.telephony.data.NrQosSessionAttributes; 31 import android.util.Log; 32 33 import com.android.modules.utils.build.SdkLevel; 34 35 import java.util.Objects; 36 37 /** 38 * Wraps callback related information and sends messages between network agent and the application. 39 * <p/> 40 * This is a satellite class of {@link com.android.server.ConnectivityService} and not meant 41 * to be used in other contexts. 42 * 43 * @hide 44 */ 45 class QosCallbackAgentConnection implements IBinder.DeathRecipient { 46 private static final String TAG = QosCallbackAgentConnection.class.getSimpleName(); 47 private static final boolean DBG = false; 48 49 private final int mAgentCallbackId; 50 @NonNull private final QosCallbackTracker mQosCallbackTracker; 51 @NonNull private final IQosCallback mCallback; 52 @NonNull private final IBinder mBinder; 53 @NonNull private final QosFilter mFilter; 54 @NonNull private final NetworkAgentInfo mNetworkAgentInfo; 55 56 private final int mUid; 57 58 /** 59 * Gets the uid 60 * @return uid 61 */ getUid()62 int getUid() { 63 return mUid; 64 } 65 66 /** 67 * Gets the binder 68 * @return binder 69 */ 70 @NonNull getBinder()71 IBinder getBinder() { 72 return mBinder; 73 } 74 75 /** 76 * Gets the callback id 77 * 78 * @return callback id 79 */ getAgentCallbackId()80 int getAgentCallbackId() { 81 return mAgentCallbackId; 82 } 83 84 /** 85 * Gets the network tied to the callback of this connection 86 * 87 * @return network 88 */ 89 @NonNull getNetwork()90 Network getNetwork() { 91 return mFilter.getNetwork(); 92 } 93 QosCallbackAgentConnection(@onNull final QosCallbackTracker qosCallbackTracker, final int agentCallbackId, @NonNull final IQosCallback callback, @NonNull final QosFilter filter, final int uid, @NonNull final NetworkAgentInfo networkAgentInfo)94 QosCallbackAgentConnection(@NonNull final QosCallbackTracker qosCallbackTracker, 95 final int agentCallbackId, 96 @NonNull final IQosCallback callback, 97 @NonNull final QosFilter filter, 98 final int uid, 99 @NonNull final NetworkAgentInfo networkAgentInfo) { 100 Objects.requireNonNull(qosCallbackTracker, "qosCallbackTracker must be non-null"); 101 Objects.requireNonNull(callback, "callback must be non-null"); 102 Objects.requireNonNull(filter, "filter must be non-null"); 103 Objects.requireNonNull(networkAgentInfo, "networkAgentInfo must be non-null"); 104 105 mQosCallbackTracker = qosCallbackTracker; 106 mAgentCallbackId = agentCallbackId; 107 mCallback = callback; 108 mFilter = filter; 109 mUid = uid; 110 mBinder = mCallback.asBinder(); 111 mNetworkAgentInfo = networkAgentInfo; 112 } 113 114 @Override binderDied()115 public void binderDied() { 116 logw("binderDied: binder died with callback id: " + mAgentCallbackId); 117 mQosCallbackTracker.unregisterCallback(mCallback); 118 } 119 unlinkToDeathRecipient()120 void unlinkToDeathRecipient() { 121 mBinder.unlinkToDeath(this, 0); 122 } 123 124 // Returns false if the NetworkAgent was never notified. sendCmdRegisterCallback()125 boolean sendCmdRegisterCallback() { 126 final int exceptionType = mFilter.validate(); 127 if (exceptionType != EX_TYPE_FILTER_NONE) { 128 try { 129 if (DBG) log("sendCmdRegisterCallback: filter validation failed"); 130 mCallback.onError(exceptionType); 131 } catch (final RemoteException e) { 132 loge("sendCmdRegisterCallback:", e); 133 } 134 return false; 135 } 136 137 try { 138 mBinder.linkToDeath(this, 0); 139 } catch (final RemoteException e) { 140 loge("failed linking to death recipient", e); 141 return false; 142 } 143 mNetworkAgentInfo.onQosFilterCallbackRegistered(mAgentCallbackId, mFilter); 144 return true; 145 } 146 sendCmdUnregisterCallback()147 void sendCmdUnregisterCallback() { 148 if (DBG) log("sendCmdUnregisterCallback: unregistering"); 149 mNetworkAgentInfo.onQosCallbackUnregistered(mAgentCallbackId); 150 } 151 sendEventEpsQosSessionAvailable(final QosSession session, final EpsBearerQosSessionAttributes attributes)152 void sendEventEpsQosSessionAvailable(final QosSession session, 153 final EpsBearerQosSessionAttributes attributes) { 154 if (!validateOrSendErrorAndUnregister()) return; 155 try { 156 if (DBG) log("sendEventEpsQosSessionAvailable: sending..."); 157 mCallback.onQosEpsBearerSessionAvailable(session, attributes); 158 } catch (final RemoteException e) { 159 loge("sendEventEpsQosSessionAvailable: remote exception", e); 160 } 161 } 162 sendEventNrQosSessionAvailable(final QosSession session, final NrQosSessionAttributes attributes)163 void sendEventNrQosSessionAvailable(final QosSession session, 164 final NrQosSessionAttributes attributes) { 165 if (!validateOrSendErrorAndUnregister()) return; 166 try { 167 if (DBG) log("sendEventNrQosSessionAvailable: sending..."); 168 mCallback.onNrQosSessionAvailable(session, attributes); 169 } catch (final RemoteException e) { 170 loge("sendEventNrQosSessionAvailable: remote exception", e); 171 } 172 } 173 sendEventQosSessionLost(@onNull final QosSession session)174 void sendEventQosSessionLost(@NonNull final QosSession session) { 175 if (!validateOrSendErrorAndUnregister()) return; 176 try { 177 if (DBG) log("sendEventQosSessionLost: sending..."); 178 mCallback.onQosSessionLost(session); 179 } catch (final RemoteException e) { 180 loge("sendEventQosSessionLost: remote exception", e); 181 } 182 } 183 sendEventQosCallbackError(@osCallbackException.ExceptionType final int exceptionType)184 void sendEventQosCallbackError(@QosCallbackException.ExceptionType final int exceptionType) { 185 try { 186 if (DBG) log("sendEventQosCallbackError: sending..."); 187 mCallback.onError(exceptionType); 188 } catch (final RemoteException e) { 189 loge("sendEventQosCallbackError: remote exception", e); 190 } 191 } 192 validateOrSendErrorAndUnregister()193 private boolean validateOrSendErrorAndUnregister() { 194 final int exceptionType = mFilter.validate(); 195 if (exceptionType != EX_TYPE_FILTER_NONE) { 196 log("validation fail before sending QosCallback."); 197 // Error callback is returned from Android T to prevent any disruption of application 198 // running on Android S. 199 if (SdkLevel.isAtLeastT()) { 200 sendEventQosCallbackError(exceptionType); 201 mQosCallbackTracker.unregisterCallback(mCallback); 202 } 203 return false; 204 } 205 return true; 206 } 207 log(@onNull final String msg)208 private static void log(@NonNull final String msg) { 209 Log.d(TAG, msg); 210 } 211 logw(@onNull final String msg)212 private static void logw(@NonNull final String msg) { 213 Log.w(TAG, msg); 214 } 215 loge(@onNull final String msg, final Throwable t)216 private static void loge(@NonNull final String msg, final Throwable t) { 217 Log.e(TAG, msg, t); 218 } 219 } 220