1 /* 2 * Copyright 2017 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; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.hardware.radio.V1_0.RegState; 22 import android.hardware.radio.V1_4.DataRegStateResult.VopsInfo.hidl_discriminator; 23 import android.os.AsyncResult; 24 import android.os.Handler; 25 import android.os.Looper; 26 import android.os.Message; 27 import android.telephony.AccessNetworkConstants; 28 import android.telephony.AccessNetworkConstants.AccessNetworkType; 29 import android.telephony.CellIdentity; 30 import android.telephony.CellIdentityCdma; 31 import android.telephony.LteVopsSupportInfo; 32 import android.telephony.NetworkRegistrationInfo; 33 import android.telephony.NetworkService; 34 import android.telephony.NetworkServiceCallback; 35 import android.telephony.ServiceState; 36 import android.telephony.SubscriptionManager; 37 import android.telephony.TelephonyManager; 38 import android.text.TextUtils; 39 40 import com.android.telephony.Rlog; 41 42 import java.util.ArrayList; 43 import java.util.HashMap; 44 import java.util.List; 45 import java.util.Map; 46 47 /** 48 * Implementation of network services for Cellular. It's a service that handles network requests 49 * for Cellular. It passes the requests to inner CellularNetworkServiceProvider which has a 50 * handler thread for each slot. 51 */ 52 public class CellularNetworkService extends NetworkService { 53 private static final boolean DBG = false; 54 55 private static final String TAG = CellularNetworkService.class.getSimpleName(); 56 57 private static final int GET_CS_REGISTRATION_STATE_DONE = 1; 58 private static final int GET_PS_REGISTRATION_STATE_DONE = 2; 59 private static final int NETWORK_REGISTRATION_STATE_CHANGED = 3; 60 61 // From 24.008 6.1.3.0 and 10.5.6.2 the maximum number of PDP Contexts is 16. 62 private static final int MAX_DATA_CALLS = 16; 63 64 private class CellularNetworkServiceProvider extends NetworkServiceProvider { 65 66 private final Map<Message, NetworkServiceCallback> mCallbackMap = new HashMap<>(); 67 68 private final Handler mHandler; 69 70 private final Phone mPhone; 71 CellularNetworkServiceProvider(int slotId)72 CellularNetworkServiceProvider(int slotId) { 73 super(slotId); 74 75 mPhone = PhoneFactory.getPhone(getSlotIndex()); 76 77 mHandler = new Handler(Looper.myLooper()) { 78 @Override 79 public void handleMessage(Message message) { 80 NetworkServiceCallback callback = mCallbackMap.remove(message); 81 82 AsyncResult ar; 83 switch (message.what) { 84 case GET_CS_REGISTRATION_STATE_DONE: 85 case GET_PS_REGISTRATION_STATE_DONE: 86 if (callback == null) return; 87 ar = (AsyncResult) message.obj; 88 int domain = (message.what == GET_CS_REGISTRATION_STATE_DONE) 89 ? NetworkRegistrationInfo.DOMAIN_CS 90 : NetworkRegistrationInfo.DOMAIN_PS; 91 NetworkRegistrationInfo netState = 92 getRegistrationStateFromResult(ar.result, domain); 93 94 int resultCode; 95 if (ar.exception != null || netState == null) { 96 resultCode = NetworkServiceCallback.RESULT_ERROR_FAILED; 97 } else { 98 resultCode = NetworkServiceCallback.RESULT_SUCCESS; 99 } 100 101 try { 102 if (DBG) { 103 log("Calling onRequestNetworkRegistrationInfoComplete." 104 + "resultCode = " + resultCode 105 + ", netState = " + netState); 106 } 107 callback.onRequestNetworkRegistrationInfoComplete( 108 resultCode, netState); 109 } catch (Exception e) { 110 loge("Exception: " + e); 111 } 112 break; 113 case NETWORK_REGISTRATION_STATE_CHANGED: 114 notifyNetworkRegistrationInfoChanged(); 115 break; 116 default: 117 return; 118 } 119 } 120 }; 121 122 mPhone.mCi.registerForNetworkStateChanged( 123 mHandler, NETWORK_REGISTRATION_STATE_CHANGED, null); 124 } 125 getRegStateFromHalRegState(int halRegState)126 private int getRegStateFromHalRegState(int halRegState) { 127 switch (halRegState) { 128 case RegState.NOT_REG_MT_NOT_SEARCHING_OP: 129 case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM: 130 return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; 131 case RegState.REG_HOME: 132 return NetworkRegistrationInfo.REGISTRATION_STATE_HOME; 133 case RegState.NOT_REG_MT_SEARCHING_OP: 134 case RegState.NOT_REG_MT_SEARCHING_OP_EM: 135 return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_SEARCHING; 136 case RegState.REG_DENIED: 137 case RegState.REG_DENIED_EM: 138 return NetworkRegistrationInfo.REGISTRATION_STATE_DENIED; 139 case RegState.UNKNOWN: 140 case RegState.UNKNOWN_EM: 141 return NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN; 142 case RegState.REG_ROAMING: 143 return NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING; 144 default: 145 return NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING; 146 } 147 } 148 isEmergencyOnly(int halRegState)149 private boolean isEmergencyOnly(int halRegState) { 150 switch (halRegState) { 151 case RegState.NOT_REG_MT_NOT_SEARCHING_OP_EM: 152 case RegState.NOT_REG_MT_SEARCHING_OP_EM: 153 case RegState.REG_DENIED_EM: 154 case RegState.UNKNOWN_EM: 155 return true; 156 case RegState.NOT_REG_MT_NOT_SEARCHING_OP: 157 case RegState.REG_HOME: 158 case RegState.NOT_REG_MT_SEARCHING_OP: 159 case RegState.REG_DENIED: 160 case RegState.UNKNOWN: 161 case RegState.REG_ROAMING: 162 default: 163 return false; 164 } 165 } 166 getAvailableServices(int regState, int domain, boolean emergencyOnly)167 private List<Integer> getAvailableServices(int regState, int domain, 168 boolean emergencyOnly) { 169 List<Integer> availableServices = new ArrayList<>(); 170 171 // In emergency only states, only SERVICE_TYPE_EMERGENCY is available. 172 // Otherwise, certain services are available only if it's registered on home or roaming 173 // network. 174 if (emergencyOnly) { 175 availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY); 176 } else if (regState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING 177 || regState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) { 178 if (domain == NetworkRegistrationInfo.DOMAIN_PS) { 179 availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA); 180 } else if (domain == NetworkRegistrationInfo.DOMAIN_CS) { 181 availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE); 182 availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_SMS); 183 availableServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VIDEO); 184 } 185 } 186 187 return availableServices; 188 } 189 getRegistrationStateFromResult(Object result, int domain)190 private NetworkRegistrationInfo getRegistrationStateFromResult(Object result, int domain) { 191 if (result == null) { 192 return null; 193 } 194 195 // TODO: unify when voiceRegStateResult and DataRegStateResult are unified. 196 if (domain == NetworkRegistrationInfo.DOMAIN_CS) { 197 return createRegistrationStateFromVoiceRegState(result); 198 } else if (domain == NetworkRegistrationInfo.DOMAIN_PS) { 199 return createRegistrationStateFromDataRegState(result); 200 } else { 201 return null; 202 } 203 } 204 getPlmnFromCellIdentity(@ullable final CellIdentity ci)205 private @NonNull String getPlmnFromCellIdentity(@Nullable final CellIdentity ci) { 206 if (ci == null || ci instanceof CellIdentityCdma) return ""; 207 208 final String mcc = ci.getMccString(); 209 final String mnc = ci.getMncString(); 210 211 if (TextUtils.isEmpty(mcc) || TextUtils.isEmpty(mnc)) return ""; 212 213 return mcc + mnc; 214 } 215 createRegistrationStateFromVoiceRegState(Object result)216 private NetworkRegistrationInfo createRegistrationStateFromVoiceRegState(Object result) { 217 final int transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 218 final int domain = NetworkRegistrationInfo.DOMAIN_CS; 219 220 // 1.5 at the top so that we can do an "early exit" from the method 221 if (result instanceof android.hardware.radio.V1_5.RegStateResult) { 222 return getNetworkRegistrationInfo( 223 domain, 224 transportType, 225 (android.hardware.radio.V1_5.RegStateResult) result); 226 } else if (result instanceof android.hardware.radio.V1_0.VoiceRegStateResult) { 227 android.hardware.radio.V1_0.VoiceRegStateResult voiceRegState = 228 (android.hardware.radio.V1_0.VoiceRegStateResult) result; 229 int regState = getRegStateFromHalRegState(voiceRegState.regState); 230 int networkType = ServiceState.rilRadioTechnologyToNetworkType(voiceRegState.rat); 231 int reasonForDenial = voiceRegState.reasonForDenial; 232 boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState); 233 boolean cssSupported = voiceRegState.cssSupported; 234 int roamingIndicator = voiceRegState.roamingIndicator; 235 int systemIsInPrl = voiceRegState.systemIsInPrl; 236 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator; 237 List<Integer> availableServices = getAvailableServices( 238 regState, domain, emergencyOnly); 239 CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity); 240 final String rplmn = getPlmnFromCellIdentity(cellIdentity); 241 242 return new NetworkRegistrationInfo(domain, transportType, regState, 243 networkType, reasonForDenial, emergencyOnly, availableServices, 244 cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl, 245 defaultRoamingIndicator); 246 } else if (result instanceof android.hardware.radio.V1_2.VoiceRegStateResult) { 247 android.hardware.radio.V1_2.VoiceRegStateResult voiceRegState = 248 (android.hardware.radio.V1_2.VoiceRegStateResult) result; 249 int regState = getRegStateFromHalRegState(voiceRegState.regState); 250 int networkType = ServiceState.rilRadioTechnologyToNetworkType(voiceRegState.rat); 251 int reasonForDenial = voiceRegState.reasonForDenial; 252 boolean emergencyOnly = isEmergencyOnly(voiceRegState.regState); 253 boolean cssSupported = voiceRegState.cssSupported; 254 int roamingIndicator = voiceRegState.roamingIndicator; 255 int systemIsInPrl = voiceRegState.systemIsInPrl; 256 int defaultRoamingIndicator = voiceRegState.defaultRoamingIndicator; 257 List<Integer> availableServices = getAvailableServices( 258 regState, domain, emergencyOnly); 259 CellIdentity cellIdentity = CellIdentity.create(voiceRegState.cellIdentity); 260 final String rplmn = getPlmnFromCellIdentity(cellIdentity); 261 262 return new NetworkRegistrationInfo(domain, transportType, regState, 263 networkType, reasonForDenial, emergencyOnly, availableServices, 264 cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl, 265 defaultRoamingIndicator); 266 } 267 268 return null; 269 } 270 createRegistrationStateFromDataRegState(Object result)271 private NetworkRegistrationInfo createRegistrationStateFromDataRegState(Object result) { 272 final int domain = NetworkRegistrationInfo.DOMAIN_PS; 273 final int transportType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN; 274 275 int regState = NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN; 276 int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 277 int reasonForDenial = 0; 278 boolean emergencyOnly = false; 279 int maxDataCalls = 0; 280 CellIdentity cellIdentity; 281 boolean isEndcAvailable = false; 282 boolean isNrAvailable = false; 283 boolean isDcNrRestricted = false; 284 285 LteVopsSupportInfo lteVopsSupportInfo = 286 new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE, 287 LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE); 288 289 // 1.5 at the top so that we can do an "early exit" from the method 290 if (result instanceof android.hardware.radio.V1_5.RegStateResult) { 291 return getNetworkRegistrationInfo( 292 domain, 293 transportType, 294 (android.hardware.radio.V1_5.RegStateResult) result); 295 } else if (result instanceof android.hardware.radio.V1_0.DataRegStateResult) { 296 android.hardware.radio.V1_0.DataRegStateResult dataRegState = 297 (android.hardware.radio.V1_0.DataRegStateResult) result; 298 regState = getRegStateFromHalRegState(dataRegState.regState); 299 networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.rat); 300 reasonForDenial = dataRegState.reasonDataDenied; 301 emergencyOnly = isEmergencyOnly(dataRegState.regState); 302 maxDataCalls = dataRegState.maxDataCalls; 303 cellIdentity = CellIdentity.create(dataRegState.cellIdentity); 304 } else if (result instanceof android.hardware.radio.V1_2.DataRegStateResult) { 305 android.hardware.radio.V1_2.DataRegStateResult dataRegState = 306 (android.hardware.radio.V1_2.DataRegStateResult) result; 307 regState = getRegStateFromHalRegState(dataRegState.regState); 308 networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.rat); 309 reasonForDenial = dataRegState.reasonDataDenied; 310 emergencyOnly = isEmergencyOnly(dataRegState.regState); 311 maxDataCalls = dataRegState.maxDataCalls; 312 cellIdentity = CellIdentity.create(dataRegState.cellIdentity); 313 } else if (result instanceof android.hardware.radio.V1_4.DataRegStateResult) { 314 android.hardware.radio.V1_4.DataRegStateResult dataRegState = 315 (android.hardware.radio.V1_4.DataRegStateResult) result; 316 regState = getRegStateFromHalRegState(dataRegState.base.regState); 317 networkType = ServiceState.rilRadioTechnologyToNetworkType(dataRegState.base.rat); 318 319 reasonForDenial = dataRegState.base.reasonDataDenied; 320 emergencyOnly = isEmergencyOnly(dataRegState.base.regState); 321 maxDataCalls = dataRegState.base.maxDataCalls; 322 cellIdentity = CellIdentity.create(dataRegState.base.cellIdentity); 323 android.hardware.radio.V1_4.NrIndicators nrIndicators = dataRegState.nrIndicators; 324 325 // Check for lteVopsInfo only if its initialized and RAT is EUTRAN 326 if (dataRegState.vopsInfo.getDiscriminator() == hidl_discriminator.lteVopsInfo 327 && ServiceState.rilRadioTechnologyToAccessNetworkType(dataRegState.base.rat) 328 == AccessNetworkType.EUTRAN) { 329 android.hardware.radio.V1_4.LteVopsInfo vopsSupport = 330 dataRegState.vopsInfo.lteVopsInfo(); 331 lteVopsSupportInfo = convertHalLteVopsSupportInfo(vopsSupport.isVopsSupported, 332 vopsSupport.isEmcBearerSupported); 333 } else { 334 lteVopsSupportInfo = 335 new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE, 336 LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE); 337 } 338 339 isEndcAvailable = nrIndicators.isEndcAvailable; 340 isNrAvailable = nrIndicators.isNrAvailable; 341 isDcNrRestricted = nrIndicators.isDcNrRestricted; 342 } else { 343 loge("Unknown type of DataRegStateResult " + result); 344 return null; 345 } 346 347 String rplmn = getPlmnFromCellIdentity(cellIdentity); 348 List<Integer> availableServices = getAvailableServices( 349 regState, domain, emergencyOnly); 350 351 return new NetworkRegistrationInfo(domain, transportType, regState, networkType, 352 reasonForDenial, emergencyOnly, availableServices, cellIdentity, rplmn, 353 maxDataCalls, isDcNrRestricted, isNrAvailable, isEndcAvailable, 354 lteVopsSupportInfo); 355 } 356 getNetworkRegistrationInfo( int domain, int transportType, android.hardware.radio.V1_5.RegStateResult regResult)357 private @NonNull NetworkRegistrationInfo getNetworkRegistrationInfo( 358 int domain, int transportType, 359 android.hardware.radio.V1_5.RegStateResult regResult) { 360 361 // Perform common conversions that aren't domain specific 362 final int regState = getRegStateFromHalRegState(regResult.regState); 363 final boolean isEmergencyOnly = isEmergencyOnly(regResult.regState); 364 final List<Integer> availableServices = getAvailableServices( 365 regState, domain, isEmergencyOnly); 366 final int rejectCause = regResult.reasonForDenial; 367 final CellIdentity cellIdentity = CellIdentity.create(regResult.cellIdentity); 368 final String rplmn = regResult.registeredPlmn; 369 final int reasonForDenial = regResult.reasonForDenial; 370 371 int networkType = ServiceState.rilRadioTechnologyToNetworkType(regResult.rat); 372 if (networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) { 373 // In Radio HAL v1.5, NETWORK_TYPE_LTE_CA is ignored. Callers should use 374 // PhysicalChannelConfig. 375 networkType = TelephonyManager.NETWORK_TYPE_LTE; 376 } 377 378 // Conditional parameters for specific RANs 379 boolean cssSupported = false; 380 int roamingIndicator = 0; 381 int systemIsInPrl = 0; 382 int defaultRoamingIndicator = 0; 383 boolean isEndcAvailable = false; 384 boolean isNrAvailable = false; 385 boolean isDcNrRestricted = false; 386 LteVopsSupportInfo vopsInfo = new LteVopsSupportInfo( 387 LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE, 388 LteVopsSupportInfo.LTE_STATUS_NOT_AVAILABLE); 389 390 switch (regResult.accessTechnologySpecificInfo.getDiscriminator()) { 391 case android.hardware.radio.V1_5.RegStateResult 392 .AccessTechnologySpecificInfo.hidl_discriminator.cdmaInfo: 393 android.hardware.radio.V1_5.RegStateResult 394 .AccessTechnologySpecificInfo.Cdma2000RegistrationInfo cdmaInfo = 395 regResult.accessTechnologySpecificInfo.cdmaInfo(); 396 cssSupported = cdmaInfo.cssSupported; 397 roamingIndicator = cdmaInfo.roamingIndicator; 398 systemIsInPrl = cdmaInfo.systemIsInPrl; 399 defaultRoamingIndicator = cdmaInfo.defaultRoamingIndicator; 400 break; 401 case android.hardware.radio.V1_5.RegStateResult 402 .AccessTechnologySpecificInfo.hidl_discriminator.eutranInfo: 403 android.hardware.radio.V1_5.RegStateResult 404 .AccessTechnologySpecificInfo.EutranRegistrationInfo eutranInfo = 405 regResult.accessTechnologySpecificInfo.eutranInfo(); 406 407 isDcNrRestricted = eutranInfo.nrIndicators.isDcNrRestricted; 408 isNrAvailable = eutranInfo.nrIndicators.isNrAvailable; 409 isEndcAvailable = eutranInfo.nrIndicators.isEndcAvailable; 410 vopsInfo = convertHalLteVopsSupportInfo( 411 eutranInfo.lteVopsInfo.isVopsSupported, 412 eutranInfo.lteVopsInfo.isEmcBearerSupported); 413 break; 414 default: 415 log("No access tech specific info passes for RegStateResult"); 416 break; 417 } 418 419 // build the result based on the domain for the request 420 switch(domain) { 421 case NetworkRegistrationInfo.DOMAIN_CS: 422 return new NetworkRegistrationInfo(domain, transportType, regState, 423 networkType, reasonForDenial, isEmergencyOnly, availableServices, 424 cellIdentity, rplmn, cssSupported, roamingIndicator, systemIsInPrl, 425 defaultRoamingIndicator); 426 default: 427 loge("Unknown domain passed to CellularNetworkService= " + domain); 428 // fall through 429 case NetworkRegistrationInfo.DOMAIN_PS: 430 return new NetworkRegistrationInfo(domain, transportType, regState, networkType, 431 reasonForDenial, isEmergencyOnly, availableServices, cellIdentity, 432 rplmn, MAX_DATA_CALLS, isDcNrRestricted, isNrAvailable, isEndcAvailable, 433 vopsInfo); 434 } 435 } 436 convertHalLteVopsSupportInfo( boolean vopsSupport, boolean emcBearerSupport)437 private LteVopsSupportInfo convertHalLteVopsSupportInfo( 438 boolean vopsSupport, boolean emcBearerSupport) { 439 int vops = LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED; 440 int emergency = LteVopsSupportInfo.LTE_STATUS_NOT_SUPPORTED; 441 442 if (vopsSupport) { 443 vops = LteVopsSupportInfo.LTE_STATUS_SUPPORTED; 444 } 445 if (emcBearerSupport) { 446 emergency = LteVopsSupportInfo.LTE_STATUS_SUPPORTED; 447 } 448 return new LteVopsSupportInfo(vops, emergency); 449 } 450 451 @Override requestNetworkRegistrationInfo(int domain, NetworkServiceCallback callback)452 public void requestNetworkRegistrationInfo(int domain, NetworkServiceCallback callback) { 453 if (DBG) log("requestNetworkRegistrationInfo for domain " + domain); 454 Message message = null; 455 456 if (domain == NetworkRegistrationInfo.DOMAIN_CS) { 457 message = Message.obtain(mHandler, GET_CS_REGISTRATION_STATE_DONE); 458 mCallbackMap.put(message, callback); 459 mPhone.mCi.getVoiceRegistrationState(message); 460 } else if (domain == NetworkRegistrationInfo.DOMAIN_PS) { 461 message = Message.obtain(mHandler, GET_PS_REGISTRATION_STATE_DONE); 462 mCallbackMap.put(message, callback); 463 mPhone.mCi.getDataRegistrationState(message); 464 } else { 465 loge("requestNetworkRegistrationInfo invalid domain " + domain); 466 callback.onRequestNetworkRegistrationInfoComplete( 467 NetworkServiceCallback.RESULT_ERROR_INVALID_ARG, null); 468 } 469 } 470 471 @Override close()472 public void close() { 473 mCallbackMap.clear(); 474 mPhone.mCi.unregisterForNetworkStateChanged(mHandler); 475 } 476 } 477 478 @Override onCreateNetworkServiceProvider(int slotIndex)479 public NetworkServiceProvider onCreateNetworkServiceProvider(int slotIndex) { 480 if (DBG) log("Cellular network service created for slot " + slotIndex); 481 if (!SubscriptionManager.isValidSlotIndex(slotIndex)) { 482 loge("Tried to Cellular network service with invalid slotId " + slotIndex); 483 return null; 484 } 485 return new CellularNetworkServiceProvider(slotIndex); 486 } 487 log(String s)488 private void log(String s) { 489 Rlog.d(TAG, s); 490 } 491 loge(String s)492 private void loge(String s) { 493 Rlog.e(TAG, s); 494 } 495 } 496