1 /* 2 * Copyright 2018 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.internal.telephony.dataconnection; 18 19 import android.net.LinkProperties; 20 import android.os.AsyncResult; 21 import android.os.Handler; 22 import android.os.Looper; 23 import android.os.Message; 24 import android.telephony.SubscriptionManager; 25 import android.telephony.data.DataCallResponse; 26 import android.telephony.data.DataProfile; 27 import android.telephony.data.DataService; 28 import android.telephony.data.DataServiceCallback; 29 30 import com.android.internal.telephony.Phone; 31 import com.android.internal.telephony.PhoneFactory; 32 import com.android.telephony.Rlog; 33 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Map; 37 38 /** 39 * This class represents cellular data service which handles telephony data requests and response 40 * from the cellular modem. 41 */ 42 public class CellularDataService extends DataService { 43 private static final String TAG = CellularDataService.class.getSimpleName(); 44 45 private static final boolean DBG = false; 46 47 private static final int SETUP_DATA_CALL_COMPLETE = 1; 48 private static final int DEACTIVATE_DATA_ALL_COMPLETE = 2; 49 private static final int SET_INITIAL_ATTACH_APN_COMPLETE = 3; 50 private static final int SET_DATA_PROFILE_COMPLETE = 4; 51 private static final int REQUEST_DATA_CALL_LIST_COMPLETE = 5; 52 private static final int DATA_CALL_LIST_CHANGED = 6; 53 54 private class CellularDataServiceProvider extends DataService.DataServiceProvider { 55 56 private final Map<Message, DataServiceCallback> mCallbackMap = new HashMap<>(); 57 58 private final Handler mHandler; 59 60 private final Phone mPhone; 61 CellularDataServiceProvider(int slotId)62 private CellularDataServiceProvider(int slotId) { 63 super(slotId); 64 65 mPhone = PhoneFactory.getPhone(getSlotIndex()); 66 67 mHandler = new Handler(Looper.myLooper()) { 68 @Override 69 public void handleMessage(Message message) { 70 DataServiceCallback callback = mCallbackMap.remove(message); 71 72 AsyncResult ar = (AsyncResult) message.obj; 73 switch (message.what) { 74 case SETUP_DATA_CALL_COMPLETE: 75 DataCallResponse response = (DataCallResponse) ar.result; 76 callback.onSetupDataCallComplete(ar.exception != null 77 ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE 78 : DataServiceCallback.RESULT_SUCCESS, 79 response); 80 break; 81 case DEACTIVATE_DATA_ALL_COMPLETE: 82 callback.onDeactivateDataCallComplete(ar.exception != null 83 ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE 84 : DataServiceCallback.RESULT_SUCCESS); 85 break; 86 case SET_INITIAL_ATTACH_APN_COMPLETE: 87 callback.onSetInitialAttachApnComplete(ar.exception != null 88 ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE 89 : DataServiceCallback.RESULT_SUCCESS); 90 break; 91 case SET_DATA_PROFILE_COMPLETE: 92 callback.onSetDataProfileComplete(ar.exception != null 93 ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE 94 : DataServiceCallback.RESULT_SUCCESS); 95 break; 96 case REQUEST_DATA_CALL_LIST_COMPLETE: 97 callback.onRequestDataCallListComplete( 98 ar.exception != null 99 ? DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE 100 : DataServiceCallback.RESULT_SUCCESS, 101 ar.exception != null 102 ? null : (List<DataCallResponse>) ar.result 103 ); 104 break; 105 case DATA_CALL_LIST_CHANGED: 106 notifyDataCallListChanged((List<DataCallResponse>) ar.result); 107 break; 108 default: 109 loge("Unexpected event: " + message.what); 110 return; 111 } 112 } 113 }; 114 115 if (DBG) log("Register for data call list changed."); 116 mPhone.mCi.registerForDataCallListChanged(mHandler, DATA_CALL_LIST_CHANGED, null); 117 } 118 119 @Override setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, DataServiceCallback callback)120 public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, 121 boolean allowRoaming, int reason, LinkProperties linkProperties, 122 DataServiceCallback callback) { 123 if (DBG) log("setupDataCall " + getSlotIndex()); 124 125 Message message = null; 126 // Only obtain the message when the caller wants a callback. If the caller doesn't care 127 // the request completed or results, then no need to pass the message down. 128 if (callback != null) { 129 message = Message.obtain(mHandler, SETUP_DATA_CALL_COMPLETE); 130 mCallbackMap.put(message, callback); 131 } 132 133 mPhone.mCi.setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, 134 reason, linkProperties, message); 135 } 136 137 @Override deactivateDataCall(int cid, int reason, DataServiceCallback callback)138 public void deactivateDataCall(int cid, int reason, DataServiceCallback callback) { 139 if (DBG) log("deactivateDataCall " + getSlotIndex()); 140 141 Message message = null; 142 // Only obtain the message when the caller wants a callback. If the caller doesn't care 143 // the request completed or results, then no need to pass the message down. 144 if (callback != null) { 145 message = Message.obtain(mHandler, DEACTIVATE_DATA_ALL_COMPLETE); 146 mCallbackMap.put(message, callback); 147 } 148 149 mPhone.mCi.deactivateDataCall(cid, reason, message); 150 } 151 152 @Override setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, DataServiceCallback callback)153 public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, 154 DataServiceCallback callback) { 155 if (DBG) log("setInitialAttachApn " + getSlotIndex()); 156 157 Message message = null; 158 // Only obtain the message when the caller wants a callback. If the caller doesn't care 159 // the request completed or results, then no need to pass the message down. 160 if (callback != null) { 161 message = Message.obtain(mHandler, SET_INITIAL_ATTACH_APN_COMPLETE); 162 mCallbackMap.put(message, callback); 163 } 164 165 mPhone.mCi.setInitialAttachApn(dataProfile, isRoaming, message); 166 } 167 168 @Override setDataProfile(List<DataProfile> dps, boolean isRoaming, DataServiceCallback callback)169 public void setDataProfile(List<DataProfile> dps, boolean isRoaming, 170 DataServiceCallback callback) { 171 if (DBG) log("setDataProfile " + getSlotIndex()); 172 173 Message message = null; 174 // Only obtain the message when the caller wants a callback. If the caller doesn't care 175 // the request completed or results, then no need to pass the message down. 176 if (callback != null) { 177 message = Message.obtain(mHandler, SET_DATA_PROFILE_COMPLETE); 178 mCallbackMap.put(message, callback); 179 } 180 181 mPhone.mCi.setDataProfile(dps.toArray(new DataProfile[dps.size()]), isRoaming, message); 182 } 183 184 @Override requestDataCallList(DataServiceCallback callback)185 public void requestDataCallList(DataServiceCallback callback) { 186 if (DBG) log("requestDataCallList " + getSlotIndex()); 187 188 Message message = null; 189 // Only obtain the message when the caller wants a callback. If the caller doesn't care 190 // the request completed or results, then no need to pass the message down. 191 if (callback != null) { 192 message = Message.obtain(mHandler, REQUEST_DATA_CALL_LIST_COMPLETE); 193 mCallbackMap.put(message, callback); 194 } 195 mPhone.mCi.getDataCallList(message); 196 } 197 198 @Override close()199 public void close() { 200 mPhone.mCi.unregisterForDataCallListChanged(mHandler); 201 } 202 } 203 204 @Override onCreateDataServiceProvider(int slotIndex)205 public DataServiceProvider onCreateDataServiceProvider(int slotIndex) { 206 log("Cellular data service created for slot " + slotIndex); 207 if (!SubscriptionManager.isValidSlotIndex(slotIndex)) { 208 loge("Tried to cellular data service with invalid slotId " + slotIndex); 209 return null; 210 } 211 return new CellularDataServiceProvider(slotIndex); 212 } 213 log(String s)214 private void log(String s) { 215 Rlog.d(TAG, s); 216 } 217 loge(String s)218 private void loge(String s) { 219 Rlog.e(TAG, s); 220 } 221 } 222