Home | History | Annotate | Download | only in service
      1 /*
      2  * Copyright (C) 2014 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.omadm.service;
     18 
     19 import android.content.BroadcastReceiver;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.SharedPreferences;
     23 import android.net.ConnectivityManager;
     24 import android.net.NetworkInfo;
     25 import android.net.wifi.WifiInfo;
     26 import android.net.wifi.WifiManager;
     27 import android.os.Bundle;
     28 import android.os.SystemProperties;
     29 import android.telephony.TelephonyManager;
     30 import android.text.TextUtils;
     31 import android.util.Log;
     32 
     33 import com.android.internal.telephony.Phone;
     34 import com.android.internal.telephony.TelephonyProperties;
     35 
     36 import java.io.File;
     37 import java.io.FileInputStream;
     38 import java.io.FileOutputStream;
     39 import java.io.IOException;
     40 import java.nio.charset.StandardCharsets;
     41 import java.text.SimpleDateFormat;
     42 import java.util.Date;
     43 import java.util.Locale;
     44 import java.util.TimeZone;
     45 
     46 public class DMIntentReceiver extends BroadcastReceiver {
     47     private static final String TAG = "DMIntentReceiver";
     48     private static final boolean DBG = DMClientService.DBG;
     49 
     50     private int mUIMode = -1;
     51 
     52     private byte[] mData;
     53 
     54     private static final String ALERT_TYPE_DOWNLOADANDUPDATE
     55             = "org.openmobilealliance.dm.firmwareupdate.downloadandupdate";
     56 
     57     private static final String RP_OPERATIONS_FACTORYRESET
     58             = "./ManagedObjects/LAWMO/Operations/FactoryReset";
     59 
     60     private static final String RP_EXT_OPERATIONS_RESET
     61             = "./ManagedObjects/LAWMO/Ext/Operations/Reset";
     62 
     63     private static final String ACTION_NOTIFY_RESULT_TO_SERVER
     64             = "com.android.omadm.service.notify_result_to_server";
     65 
     66     private static final String ACTION_NOTIFY_START_UP_DMSERVICE
     67             = "com.android.omadm.service.start_up";
     68 
     69     private static final String DEV_DETAIL = "devdetail";
     70 
     71     private static final String WIFI_MAC_ADDR = "wifimacaddr";
     72 
     73     private static final String PRE_FW_VER = "prefwversion";
     74 
     75     private static final String CURR_FW_VER = "currfwversion";
     76 
     77     private static final String LAST_UPD_TIME = "lastupdatetime";
     78 
     79     private static boolean initialWapPending;
     80 
     81     @Override
     82     public void onReceive(Context context, Intent intent) {
     83         if (DMHelper.disableIfSecondaryUser(context)) {
     84             return;
     85         }
     86 
     87         String action = intent.getAction();
     88 
     89         logd("Received new intent: " + action);
     90 
     91         if (action.equals(DMIntent.ACTION_WAP_PUSH_RECEIVED_INTERNAL)) {
     92             handleWapPushIntent(context, intent);
     93         } else if (action.equals(DMIntent.ACTION_CLOSE_NOTIFICATION_INFO)) {
     94             DMHelper.cancelNotification(context, DMHelper.NOTIFICATION_INFORMATIVE_ID);
     95         } else if (action.equals(DMIntent.ACTION_USER_CONFIRMED_DM_SESSION)) {
     96             handleUserConfirmedSession(context);
     97         } else if (action.equals(DMIntent.ACTION_CLIENT_INITIATED_FOTA_SESSION)) {
     98             handleClientInitiatedFotaIntent(context, intent);
     99         } else if (action.equals(DMIntent.ACTION_TIMER_ALERT)) {
    100             handleTimeAlertIntent(context);
    101         } else if (action.equals(DMIntent.DM_SERVICE_RESULT_INTENT)) {
    102             handleDmServiceResult(context, intent);
    103         } else if (action.equals(ACTION_NOTIFY_RESULT_TO_SERVER)) {
    104             // FIXME old comment: change this to the DMIntent name
    105             handleNotifyResultToServer(context, intent);
    106         } else if (action.equals(DMIntent.ACTION_DATA_CONNECTION_READY)) {
    107             handleDataConnectionReady(context);
    108         } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
    109             logd("Ignoring Intent.ACTION_BOOT_COMPLETED");
    110             //if (!(isPhoneTypeLTE() || isPhoneTypeCDMA3G(context))) {
    111             //    saveDevDetail(context);
    112             //    handleBootCompletedIntent(context);
    113             //}
    114         } else if (action.equals(ACTION_NOTIFY_START_UP_DMSERVICE)) {
    115             if (isPhoneTypeLTE()) {
    116                 saveDevDetail(context);
    117                 SharedPreferences p = context.getSharedPreferences(DMHelper.IMEI_PREFERENCE_KEY, 0);
    118                 String currGsmImei = p.getString(DMHelper.IMEI_VALUE_KEY, "");
    119                 if (currGsmImei != null && currGsmImei.equals(intent.getStringExtra("gsmimei"))) {
    120                     logd("IMEI already stored, continuing");
    121                 } else {
    122                     SharedPreferences.Editor ed = p.edit();
    123                     ed.putString(DMHelper.IMEI_VALUE_KEY, intent.getStringExtra("gsmimei"));
    124                     ed.apply();
    125                 }
    126             } else if (isPhoneTypeCDMA3G(context)) {
    127                 SharedPreferences p = context.getSharedPreferences(DMHelper.AKEY_PREFERENCE_KEY, 0);
    128                 SharedPreferences.Editor ed = p.edit();
    129                 ed.putString(DMHelper.AKEY_VALUE_KEY, intent.getStringExtra("akey"));
    130                 ed.apply();
    131             }
    132             handleBootCompletedIntent(context);
    133         } else if (action.equals(DMIntent.ACTION_INJECT_PACKAGE_0_INTERNAL)) {
    134             String strServerID = intent.getStringExtra(DMIntent.FIELD_SERVERID);
    135             if (strServerID == null || strServerID.trim().isEmpty()) {
    136                 logd("Error! Can't inject package0. The required extras parameter '" +
    137                         DMIntent.FIELD_SERVERID + "' is null or an empty string.");
    138                 return;
    139             }
    140 
    141             Intent newIntent = new Intent(DMIntent.LAUNCH_INTENT);
    142             newIntent.putExtra(DMIntent.FIELD_REQUEST_ID, System.currentTimeMillis());
    143             newIntent.putExtra(DMIntent.FIELD_TYPE, DMIntent.TYPE_CLIENT_SESSION_REQUEST);
    144             newIntent.putExtra(DMIntent.FIELD_SERVERID, strServerID);
    145             logd("XXX received ACTION_INJECT_PACKAGE_0_INTERNAL, starting"
    146                     + " TYPE_CLIENT_SESSION_REQUEST with ID "
    147                     + newIntent.getLongExtra(DMIntent.FIELD_REQUEST_ID, 1234));
    148             newIntent.setClass(context, DMClientService.class);
    149             context.startService(newIntent);
    150         } else if (action.equals(DMIntent.ACTION_SET_SERVER_CONFIG)) {
    151             logd("ACTION_SET_SERVER_CONFIG received");
    152             String hostUrl = intent.getStringExtra(DMIntent.FIELD_SERVER_URL);
    153             String proxyAddress = intent.getStringExtra(DMIntent.FIELD_PROXY_ADDRESS);
    154             logd("server URL: " + hostUrl + " proxy address: " + proxyAddress);
    155             DMHelper.setServerUrl(context, hostUrl);
    156             DMHelper.setProxyHostname(context, proxyAddress);
    157         } else if (action.equals(DMIntent.ACTION_CANCEL_SESSION)) {
    158             // create intent and start DM service
    159             Intent newIntent = new Intent(DMIntent.LAUNCH_INTENT);
    160             newIntent.putExtra(DMIntent.FIELD_TYPE, DMIntent.TYPE_CANCEL_DM_SESSION);
    161             logd("cancelling DM Session");
    162             newIntent.setClass(context, DMClientService.class);
    163             context.startService(newIntent);
    164         }
    165     }
    166 
    167     // handle client-initiated FOTA intents
    168     private void handleClientInitiatedFotaIntent(Context context, Intent intent) {
    169         String strServerID = intent.getStringExtra(DMIntent.FIELD_SERVERID);
    170         if (TextUtils.isEmpty(strServerID)) {
    171             logd("Error! Can't start FOTA session: " +
    172                     DMIntent.FIELD_SERVERID + " is null or an empty string.");
    173             return;
    174         }
    175 
    176         String alertString = intent.getStringExtra(DMIntent.FIELD_ALERT_STR);
    177         if (TextUtils.isEmpty(alertString)) {
    178             logd("Error! Can't start FOTA session: " +
    179                     DMIntent.FIELD_ALERT_STR + " is null or an empty string.");
    180             return;
    181         }
    182 
    183         setState(context, DMHelper.STATE_APPROVED_BY_USER);
    184         long requestID = System.nanoTime();
    185 
    186         // Save pending info here
    187         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    188         SharedPreferences.Editor ed = p.edit();
    189         ed.putInt(DMHelper.DM_SESSION_TYPE_KEY, DMIntent.TYPE_FOTA_CLIENT_SESSION_REQUEST);
    190         ed.putLong(DMHelper.MESSAGE_TIMESTAMP_ID_KEY, requestID);
    191         ed.putString(DMHelper.FOTA_SERVER_ID_KEY, strServerID);
    192         ed.putString(DMHelper.FOTA_ALERT_STRING_KEY, alertString);
    193         ed.apply();
    194 
    195         if (isWifiConnected(context) || isDataNetworkAcceptable(context)) {
    196             if (!isWifiConnected(context) && isDataNetworkAcceptable(context) && isPhoneTypeLTE()) {
    197                 logd("handleClientInitiatedFotaIntent, start apn monitoring service"
    198                         + " for requestID " + requestID);
    199                 setFotaApnState(context, DMHelper.FOTA_APN_STATE_START_DM_SESSION);
    200                 startDataConnectionService(context);
    201             } else {
    202                 logd("handleClientInitiatedFotaIntent starting DM session");
    203                 startDMSession(context);
    204             }
    205         } else {
    206             logd("handleClientInitiatedFotaIntent: start data/call state monitoring");
    207             startDataConnectionService(context);
    208         }
    209     }
    210 
    211     // handle SMS and WAP Push intents;
    212     private void handleWapPushIntent(Context context, Intent intent) {
    213 
    214         int currentState = getState(context);
    215 
    216         logd("handleWapPushIntent() current state: " + currentState);
    217 
    218         // if current state is already "session in progress" - ignore new message;
    219         // otherwise remove old message and process a new one.
    220         if (currentState == DMHelper.STATE_SESSION_IN_PROGRESS) {
    221             loge("current state is 'Session-in-Progress', ignoring new message.");
    222             return;
    223         }
    224 
    225         DMHelper.cleanAllResources(context);
    226 
    227         //clean fota apn resources and stop using fota apn
    228         if (isPhoneTypeLTE()) {
    229             int mgetFotaApnState = getFotaApnState(context);
    230             logd("handleWapPushIntent, check if necessary to stop using fota apn "
    231                     + mgetFotaApnState);
    232             if (mgetFotaApnState != DMHelper.FOTA_APN_STATE_INIT) {
    233                 // resetting FOTA APN STATE
    234                 logd("XXX resetting FOTA APN state");
    235                 setFotaApnState(context, DMHelper.FOTA_APN_STATE_INIT);
    236                 stopUsingFotaApn(context);
    237                 DMHelper.cleanFotaApnResources(context);
    238             }
    239         }
    240 
    241         //parse & save message; get UI mode
    242         boolean result = parseAndSaveWapPushMessage(context, intent);
    243 
    244         if (!result) {
    245             loge("handleWapPushIntent(): error in parseAndSaveWapPushMessage()");
    246             DMHelper.cleanAllResources(context);
    247             return;
    248         }
    249 
    250         if (treeExist(context) || !isPhoneTypeLTE()) {
    251             //check UI mode and prepare and start process
    252             preprocess(context, currentState);
    253         } else {
    254             logd("WapPush arrived before tree initialization");
    255             initialWapPending = true;
    256             Intent intentConnmoInit = new Intent("com.android.omadm.service.wait_timer_alert");
    257             context.sendBroadcast(intentConnmoInit);
    258         }
    259     }
    260 
    261     private void handleUserConfirmedSession(Context context) {
    262         // check if message is not expired
    263         if (DMHelper.isMessageExpired(context)) {
    264             DMHelper.cleanAllResources(context);
    265             logd("handleUserConfirmedSession(): message is expired.");
    266             return;
    267         }
    268 
    269         startProcess(context);
    270     }
    271 
    272     // handle boot completed intent
    273     private void handleBootCompletedIntent(Context context) {
    274         // Check if DM tree already has been generated. Start service to generate tree
    275         // in case if required. It may happened only once during first boot.
    276         if (!treeExist(context)) {
    277             logd("Boot completed: there is no DM Tree. Start service to generate tree.");
    278             Intent intent = new Intent(DMIntent.LAUNCH_INTENT);
    279             intent.putExtra("NodePath", ".");
    280             intent.putExtra(DMIntent.FIELD_REQUEST_ID, -2L);
    281             intent.setClass(context, DMClientService.class);
    282             context.startService(intent);
    283             if (!initialWapPending) {
    284                 logd("handleBootCompletedIntent, no initial WapPush pending.");
    285                 DMHelper.cleanAllResources(context);
    286                 return;
    287             } else {
    288                 logd("handleBootCompletedIntent, initial WapPush pending.");
    289                 initialWapPending = false;
    290                 setState(context, DMHelper.STATE_PENDING_MESSAGE);
    291             }
    292         }
    293 
    294 //        if (isPhoneTypeLTE()) {
    295 //            int fotaApnState = getFotaApnState(context);
    296 //            logd("handleBootCompletedIntent, check if need to stop using fota apn "
    297 //                    + fotaApnState);
    298 //            if (fotaApnState != DMHelper.FOTA_APN_STATE_INIT) {
    299                 // resetting FOTA APN STATE
    300 //                setFotaApnState(context, DMHelper.FOTA_APN_STATE_INIT);
    301                 //stopUsingFotaApn();
    302 //                DMHelper.cleanFotaApnResources(context);
    303 //            }
    304             // stopUsingFotaApn();
    305 //        }
    306 
    307         int currentState = getState(context);
    308 
    309         if (currentState == DMHelper.STATE_IDLE) {
    310             logd("Boot completed: there is no message to proceed.");
    311             return;
    312         }
    313 
    314         // check if message is not expired
    315         if (DMHelper.isMessageExpired(context)) {
    316             DMHelper.cleanAllResources(context);
    317             logd("handleBootCompletedIntent(): the message is expired.");
    318             return;
    319         }
    320 
    321         // initiate mUIMode and mData from preferences
    322         if (!initFromSharedPreferences(context)) {
    323             DMHelper.cleanAllResources(context);
    324             logd("handleBootCompletedIntent(): cannot init from shared preferences");
    325             return;
    326         }
    327 
    328         preprocess(context, currentState);
    329     }
    330 
    331     // handle time alert intent (all instances)
    332     private void handleTimeAlertIntent(Context context) {
    333         int currentState = getState(context);
    334         switch (currentState) {
    335             case DMHelper.STATE_IDLE:
    336                 // nothing there
    337                 DMHelper.cleanAllResources(context);
    338                 logd("Time alert: there is no message to proceed.");
    339                 break;
    340         }
    341 
    342         if (currentState == DMHelper.STATE_IDLE) {
    343             // nothing there
    344             DMHelper.cleanAllResources(context);
    345             logd("Time alert: there is no message to proceed.");
    346         } else if (DMHelper.isMessageExpired(context)) {
    347             // check if message is not expired
    348             DMHelper.cleanAllResources(context);
    349             logd("Warning from handleTimeAlertIntent(): the message is expired.");
    350         } else if (currentState == DMHelper.STATE_SESSION_IN_PROGRESS) {
    351             // session in progress; doing nothing.
    352             logd("Time alert: session in progress; doing nothing.");
    353             DMHelper.subscribeForTimeAlert(context,
    354                     DMHelper.TIME_CHECK_STATUS_AFTER_STARTING_DM_SERVICE);
    355         } else if (currentState == DMHelper.STATE_APPROVED_BY_USER) {
    356             // approved by user: try to start session or data/call monitoring service
    357             logd("Time alert: state 'approved by user'; starting process");
    358             startProcess(context);
    359         } else if (currentState == DMHelper.STATE_PENDING_MESSAGE) {
    360             // approved by user: try to start session or data/call monitoring service pending
    361             logd("Time alert: state 'pending message'; read from preferences starting preprocess");
    362 
    363             // initiate mUIMode and mData from preferences
    364             if (!initFromSharedPreferences(context)) {
    365                 DMHelper.cleanAllResources(context);
    366                 logd("Warning from handleTimeAlertIntent(): cannot init from shared preferences");
    367                 return;
    368             }
    369             preprocess(context, currentState);
    370         } else {
    371             loge("Error from handleTimeAlertIntent(): unknown state " + currentState);
    372         }
    373     }
    374 
    375     private static void handleNotifyResultToServer(Context context, Intent intent) {
    376         logd("Inside handleNotifyResultToServer");
    377 
    378         // Save message
    379         SharedPreferences p = context.getSharedPreferences(DMHelper.FOTA_APN_PREFERENCE_KEY, 0);
    380         SharedPreferences.Editor ed = p.edit();
    381 
    382         ed.putString(DMHelper.LAWMO_RESULT_KEY, intent.getStringExtra(DMIntent.FIELD_LAWMO_RESULT));
    383         ed.putString(DMHelper.FOTA_RESULT_KEY, intent.getStringExtra(DMIntent.FIELD_FOTA_RESULT));
    384         ed.putString(DMHelper.PKG_URI_KEY, intent.getStringExtra(DMIntent.FIELD_PKGURI));
    385         ed.putString(DMHelper.ALERT_TYPE_KEY, intent.getStringExtra(DMIntent.FIELD_ALERTTYPE));
    386         ed.putString(DMHelper.CORRELATOR_KEY, intent.getStringExtra(DMIntent.FIELD_CORR));
    387         ed.putString(DMHelper.SERVER_ID_KEY, intent.getStringExtra(DMIntent.FIELD_SERVERID));
    388 
    389         ed.apply();
    390 
    391         if (isDataNetworkAcceptable(context) && !isWifiConnected(context) && isPhoneTypeLTE()) {
    392             int mgetFotaApnState = getFotaApnState(context);
    393             if (mgetFotaApnState != DMHelper.FOTA_APN_STATE_INIT) {
    394                 logd("there must be a pending session, return");
    395                 return;
    396             }
    397             // for LTE and eHRPD coverage , switch the apn before FDM
    398             logd("handleNotifyResultToServer starting FOTA APN");
    399             setFotaApnState(context, DMHelper.FOTA_APN_STATE_REPORT_DM_SESSION);
    400             startDataConnectionService(context);
    401         } else {
    402             sendNotifyIntent(context);
    403         }
    404     }
    405 
    406     // start session if we have network connectivity
    407     private void handleDataConnectionReady(Context context) {
    408         logd("Inside handleDataConnectionReady");
    409         int fotaApnState = getFotaApnState(context);
    410         logd("FOTA APN state is " + fotaApnState);
    411 
    412         if (fotaApnState == DMHelper.FOTA_APN_STATE_REPORT_DM_SESSION) {
    413             setFotaApnState(context, DMHelper.FOTA_APN_STATE_REPORT_DM_SESSION_RPTD);
    414             sendNotifyIntent(context);
    415         } else if (fotaApnState == DMHelper.FOTA_APN_STATE_START_DM_SESSION) {
    416             setFotaApnState(context, DMHelper.FOTA_APN_STATE_START_DM_SESSION_RPTD);
    417             // check if message is not expired
    418             if (DMHelper.isMessageExpired(context)) {
    419                 DMHelper.cleanAllResources(context);
    420                 logd("Warning from handleApnStateActive(): the message is expired.");
    421                 return;
    422             }
    423 
    424             int currentState = getState(context);
    425 
    426             // nothing to do here
    427             if (currentState == DMHelper.STATE_IDLE) {
    428                 DMHelper.cleanAllResources(context);
    429                 logd("handleApnStateActive(): there is no message to proceed.");
    430                 return;
    431             }
    432 
    433             if (currentState == DMHelper.STATE_SESSION_IN_PROGRESS) {
    434                 logd("handleApnStateActive(): session in progress; doing nothing.");
    435                 return;
    436             }
    437 
    438             startDMSession(context);
    439         } else {
    440             logd("handleApnStateActive: NO ACTION NEEDED");
    441         }
    442     }
    443 
    444     // check UI mode and prepare and start process
    445     private void preprocess(Context context, int currentState) {
    446 
    447         setState(context, currentState);
    448 
    449         logd("From preprocess().... Current state = " + currentState);
    450 
    451         // check UI mode. If updates has been replaced with the new one and user already
    452         // confirmed - we are skipping confirmation.
    453         if (mUIMode == DMHelper.UI_MODE_CONFIRMATION
    454                 && currentState != DMHelper.STATE_APPROVED_BY_USER) {
    455 
    456             // user confirmation is required
    457             logd("User confirmation is required");
    458             DMHelper.postConfirmationNotification(context);
    459             setState(context, DMHelper.STATE_PENDING_MESSAGE);
    460 
    461             // check and repost notification in case user cancels it
    462             DMHelper.subscribeForTimeAlert(context,
    463                     DMHelper.TIME_CHECK_NOTIFICATION_AFTER_SUBSCRIPTION);
    464 
    465             return;
    466         }
    467 
    468         if (mUIMode == DMHelper.UI_MODE_INFORMATIVE) {
    469             // required notification, just inform the user
    470             logd("User notification is required");
    471             DMHelper.postInformativeNotification_message1(context);
    472         } else {
    473             logd("Silent DM session: silent mode or user already has approved.");
    474         }
    475 
    476         // try to start DM session or start Data and Call State Monitoring Service
    477         startProcess(context);
    478     }
    479 
    480     // parse data from intent; set UI mode; save required data.
    481     private boolean parseAndSaveWapPushMessage(Context context, Intent intent) {
    482 
    483         // Parse message
    484         Bundle bdl = intent.getExtras();
    485         byte[] data = bdl.getByteArray("data");
    486         mData = data;
    487 
    488         if (data == null || data.length < 25) {
    489             loge("parseAndSaveWapPushMessage: data[] is null or length < 25.");
    490             return false;
    491         }
    492 
    493         // first 16 bytes - digest
    494         int version = ((data[17] >> 6) & 0x3) | ((data[16]) << 2);
    495         int uiMode = (data[17] >> 4) & 0x3;
    496         int indicator = (data[17] >> 3) & 0x1;
    497         int sessionId = ((data[21] & 0xff) << 8) | data[22];
    498         int serverIdLength = data[23];    // must be equal to data.length-24
    499 
    500         if (serverIdLength <= 0) {
    501             loge("parseAndSaveWapPushMessage: serverIdLength is invalid: " + serverIdLength);
    502             return false;
    503         }
    504 
    505         String serverId = new String(data, 24, serverIdLength, StandardCharsets.UTF_8);
    506         mUIMode = uiMode;
    507 
    508         // fixme: treating invalid uimode as informative for now for Sprint
    509         if(mUIMode != DMHelper.UI_MODE_CONFIRMATION && mUIMode != DMHelper.UI_MODE_INFORMATIVE) {
    510             TelephonyManager tm = TelephonyManager.from(context);
    511             String simOperator = tm.getSimOperator();
    512             String imsi = tm.getSubscriberId();
    513             Log.d(TAG, "simOperator: " + simOperator + " IMSI: " + imsi);
    514             if ("310120".equals(simOperator) || (imsi != null && imsi.startsWith("310120"))) {
    515                 loge("parseAndSaveWapPushMessage: UICC is sprint. Received uimode " + uiMode +
    516                         "; changing to informative");
    517                 mUIMode = DMHelper.UI_MODE_INFORMATIVE;
    518             }
    519         }
    520 
    521         if (DBG) {
    522             Log.i(TAG, "Get Provision Package0"
    523                     + " version:" + version
    524                     + " uiMode:" + uiMode
    525                     + " indicator:" + indicator
    526                     + " sessionId:" + sessionId
    527                     + " serverId:" + serverId);
    528         }
    529 
    530         // Save message
    531         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    532         SharedPreferences.Editor ed = p.edit();
    533         //ed.putInt("type", DMIntent.TYPE_PKG0_NOTIFICATION);
    534         //ed.putLong(DMHelper.REQUEST_ID_KEY, System.currentTimeMillis());
    535         ed.putInt("length", data.length);
    536         ed.putInt(DMHelper.DM_SESSION_TYPE_KEY, DMIntent.TYPE_PKG0_NOTIFICATION);
    537         ed.putLong(DMHelper.MESSAGE_TIMESTAMP_ID_KEY, System.nanoTime());
    538         ed.putInt(DMHelper.DM_UI_MODE_KEY, mUIMode);
    539 
    540         ed.apply();
    541 
    542 //        PendingResult pendingResult = goAsync();
    543 //        DMParseSaveWapMsgRunnable dmParseSaveWapMsgRunnable
    544 //                = new DMParseSaveWapMsgRunnable(pendingResult);
    545 //        Thread dmParseSaveWapMsgThread = new Thread(dmParseSaveWapMsgRunnable);
    546 //        dmParseSaveWapMsgThread.start();
    547 
    548         // TODO: move to worker thread
    549         try {
    550             FileOutputStream out = new FileOutputStream(DMHelper.POSTPONED_DATA_PATH);
    551             out.write(mData);
    552             out.close();
    553         } catch (IOException e) {
    554             loge("IOException while creating dmpostponed.dat", e);
    555         }
    556 
    557         return true;
    558     }
    559 
    560 // TODO: remove or uncomment to use for saving file asynchronously
    561 //    class DMParseSaveWapMsgRunnable implements Runnable {
    562 //        /** Pending result to call finish() when thread returns. */
    563 //        private final PendingResult mPendingResult;
    564 //
    565 //        DMParseSaveWapMsgRunnable(PendingResult pendingResult) {
    566 //            mPendingResult = pendingResult;
    567 //        }
    568 //
    569 //        @Override
    570 //        public void run() {
    571 //            logd("Enter dmParseSaveWapMsgThread tid=" + Thread.currentThread().getId());
    572 //            try {
    573 //                FileOutputStream out = new FileOutputStream(DMHelper.POSTPONED_DATA_PATH);
    574 //                out.write(mData);
    575 //                out.close();
    576 //            } catch (IOException e) {
    577 //                loge("IOException while creating dmpostponed.dat", e);
    578 //            } finally {
    579 //                mPendingResult.finish();
    580 //            }
    581 //        }
    582 //    }
    583 
    584     //try to start DM session or starts Data and Call State Monitoring Service
    585     private void startProcess(Context context) {
    586         //wrj348 - VZW customization: reject the wap push if phone is in ECB mode or Roaming
    587         if (!allowDMSession()) {
    588             return;
    589         }
    590         setState(context, DMHelper.STATE_APPROVED_BY_USER);
    591 
    592         // Start DM session if wifi is available.
    593         if (isWifiConnected(context)) {
    594             startDMSession(context);
    595         } else {
    596             // request FOTA APN
    597             logd("startProcess(), start data connection service");
    598             setFotaApnState(context, DMHelper.FOTA_APN_STATE_START_DM_SESSION);
    599             startDataConnectionService(context);
    600         }
    601     }
    602 
    603     private static boolean allowDMSession() {
    604         if (isInECBMode()) {
    605             return false;
    606         }
    607 
    608         Log.i(TAG, "DMSession allowed - don't reject");
    609         return true;
    610     }
    611 
    612     /**
    613      * Returns whether phone is in emergency callback mode.
    614      * @return true if the phone is in ECB mode; false if not
    615      */
    616     private static boolean isInECBMode() {
    617         boolean ecbMode = SystemProperties.getBoolean(
    618                 TelephonyProperties.PROPERTY_INECM_MODE, false);
    619         Log.i(TAG, "Phone ECB status: " + ecbMode);
    620         return ecbMode;
    621     }
    622 
    623     //start DM session.
    624     private void startDMSession(Context context) {
    625         logd("startDMSession");
    626         // get request ID from the shared preferences (the message time stamp used)
    627         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    628 
    629         long requestID = p.getLong(DMHelper.MESSAGE_TIMESTAMP_ID_KEY, -1);
    630         int type = p.getInt(DMHelper.DM_SESSION_TYPE_KEY, -1);
    631 
    632         // create intent and start DM service
    633         Intent intent = new Intent(DMIntent.LAUNCH_INTENT);
    634         intent.putExtra(DMIntent.FIELD_REQUEST_ID, requestID);
    635         intent.putExtra(DMIntent.FIELD_TYPE, type);
    636 
    637         if (type == DMIntent.TYPE_FOTA_CLIENT_SESSION_REQUEST) {
    638             String serverID = p.getString(DMHelper.FOTA_SERVER_ID_KEY, null);
    639             String alertString = p.getString(DMHelper.FOTA_ALERT_STRING_KEY, null);
    640             intent.putExtra(DMIntent.FIELD_TYPE, DMIntent.TYPE_FOTA_CLIENT_SESSION_REQUEST);
    641             intent.putExtra(DMIntent.FIELD_SERVERID, serverID);
    642             intent.putExtra(DMIntent.FIELD_ALERT_STR, alertString);
    643             logd("starting TYPE_FOTA_CLIENT_SESSION_REQUEST: serverID="
    644                     + serverID + " alertString=" + alertString
    645                     + " requestID=" + requestID);
    646         } else {
    647             // package 0 notification
    648             intent.putExtra(DMIntent.FIELD_TYPE, type);
    649 
    650             if (mData == null) { // session has not been started right away after receiving a message.
    651                 mData = setDataFromFile(context);
    652 
    653                 if (mData == null) {
    654                     logd("Error. Cannot read data from file dmpostponed.dat");
    655                     DMHelper.cleanAllResources(context);
    656                     return;
    657                 }
    658             }
    659 
    660             intent.putExtra(DMIntent.FIELD_PKG0, mData);
    661         }
    662 
    663         increaseDMSessionAttempt(context);
    664 
    665         setState(context, DMHelper.STATE_SESSION_IN_PROGRESS);
    666 
    667         DMHelper.subscribeForTimeAlert(context,
    668                 DMHelper.TIME_CHECK_STATUS_AFTER_STARTING_DM_SERVICE);
    669 
    670         intent.setClass(context, DMClientService.class);
    671         context.startService(intent);
    672     }
    673 
    674     // start data connection service
    675     private static void startDataConnectionService(Context context) {
    676         logd("Inside startDataConnectionService");
    677         DMHelper.subscribeForTimeAlert(context,
    678                 DMHelper.TIME_CHECK_STATUS_AFTER_STARTING_MONITORING_SERVICE);
    679         Intent intent = new Intent(DMIntent.ACTION_START_DATA_CONNECTION_SERVICE);
    680         intent.setClass(context, DMDataConnectionService.class);
    681         context.startService(intent);
    682     }
    683 
    684     // stop data connection service
    685     private static void stopDataConnectionService(Context context) {
    686         logd("Inside stopDataConnectionService");
    687         Intent intent = new Intent(DMIntent.ACTION_START_DATA_CONNECTION_SERVICE);
    688         intent.setClass(context, DMDataConnectionService.class);
    689         context.stopService(intent);
    690     }
    691 
    692     // Verify session result: if result is successful, clean all resources.
    693     // Otherwise, try to resubmit session request.
    694     private void handleDmServiceResult(Context context, Intent intent) {
    695         // check if request ID from incoming intent match to the one which has been sent and saved
    696         // get request ID from the shared preferences (the message time stamp used)
    697         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    698         SharedPreferences.Editor ed = p.edit();
    699         long savedRequestId = p.getLong(DMHelper.MESSAGE_TIMESTAMP_ID_KEY, 0);
    700         long receivedRequestId = intent.getLongExtra(DMIntent.FIELD_REQUEST_ID, -1);
    701 
    702         if (receivedRequestId == -2) {
    703             logd("handleDmServiceResult, tree initialisation session.");
    704             return;
    705         }
    706 
    707         // clear fota apn resources and stop using fota apn
    708         if (isPhoneTypeLTE()) {
    709             int fotaApnState = getFotaApnState(context);
    710             logd("handleDmServiceResult, chk if need to stop using fota apn "
    711                     + fotaApnState);
    712             if (fotaApnState != DMHelper.FOTA_APN_STATE_INIT) {
    713                 // resetting FOTA APN STATE
    714                 setFotaApnState(context, DMHelper.FOTA_APN_STATE_INIT);
    715                 stopUsingFotaApn(context);
    716                 // removing shared prefs settings
    717                 DMHelper.cleanFotaApnResources(context);
    718             }
    719             stopUsingFotaApn(context);
    720         }
    721 
    722         if (savedRequestId != receivedRequestId) {
    723             loge("request ID " + receivedRequestId + " from result intent doesn't "
    724                     + "match saved request ID " + savedRequestId + ", ignored");
    725 //            return;
    726         }
    727 
    728         int sessionResult = intent.getIntExtra(DMIntent.FIELD_DMRESULT, -1);
    729 
    730         int uiMode = p.getInt(DMHelper.DM_UI_MODE_KEY, -1);
    731         mUIMode = uiMode;
    732         logd("mUIMode is: " + uiMode);
    733         if (uiMode == DMHelper.UI_MODE_INFORMATIVE) {
    734             if (sessionResult == DMResult.SYNCML_DM_SUCCESS) {
    735                 logd("Displaying success notification message2");
    736                 DMHelper.postInformativeNotification_message2_success(context);
    737             } else {
    738                 logd("Displaying Fail notification message2");
    739                 DMHelper.postInformativeNotification_message2_fail(context);
    740             }
    741             ed.putInt(DMHelper.DM_UI_MODE_KEY, -1);
    742             ed.apply();
    743         }
    744 
    745         if (sessionResult == DMResult.SYNCML_DM_SUCCESS) {
    746             DMHelper.cleanAllResources(context);
    747             logd("Finished success.");
    748             return;
    749         }
    750 
    751         if (!canRestartSession(context, p)) {
    752             DMHelper.cleanAllResources(context);
    753             return;
    754         }
    755 
    756         // update status in the preferences
    757         setState(context, DMHelper.STATE_APPROVED_BY_USER);
    758 
    759         //subscribe for the time alert to start DM session again after TIME_BETWEEN_SESSION_ATTEMPTS.
    760         DMHelper.subscribeForTimeAlert(context, DMHelper.TIME_BETWEEN_SESSION_ATTEMPTS);
    761     }
    762 
    763     // check if session request can be resubmitted (if message still valid and
    764     // number of tries doesn't exceed MAX)
    765     private static boolean canRestartSession(Context context, SharedPreferences p) {
    766         int numberOfSessionAttempts = p.getInt(DMHelper.DM_SESSION_ATTEMPTS_KEY, -1);
    767 
    768         // check if max number has not been exceeded
    769         if (numberOfSessionAttempts > DMHelper.MAX_SESSION_ATTEMPTS) {
    770             logd("Error. Number of attempts to start DM session exceed MAX.");
    771             return false;
    772         }
    773 
    774         // check if message is expired or not
    775         if (DMHelper.isMessageExpired(context)) {
    776             logd("Error from canRestartSession(): the message is expired.");
    777             return false;
    778         }
    779 
    780         return true;
    781     }
    782 
    783     // set current state
    784     private static void setState(Context context, int state) {
    785         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    786         SharedPreferences.Editor ed = p.edit();
    787         ed.putInt(DMHelper.STATE_KEY, state);
    788         ed.apply();
    789     }
    790 
    791     /**
    792      * Get current state from shared prefs. If state is "Session In Progress", verify that the DM
    793      * session didn't fail and also has the same status, otherwise current state will be changed
    794      * to "Approved by User" and will be ready to handle a request for a new DM session.
    795      *
    796      * @param context the context to use
    797      * @return the current state
    798      */
    799     private static int getState(Context context) {
    800         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    801         int currentState = p.getInt(DMHelper.STATE_KEY, 0);
    802 
    803         if (currentState == DMHelper.STATE_SESSION_IN_PROGRESS
    804                 && !DMClientService.sIsDMSessionInProgress) {
    805             currentState = DMHelper.STATE_APPROVED_BY_USER;
    806             setState(context, currentState);
    807         }
    808         return currentState;
    809     }
    810 
    811     // increase attempt to start DM session
    812     private static void increaseDMSessionAttempt(Context context) {
    813         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    814         int numberOfSessionAttempts = p.getInt(DMHelper.DM_SESSION_ATTEMPTS_KEY, 0);
    815         SharedPreferences.Editor ed = p.edit();
    816         ed.putInt(DMHelper.DM_SESSION_ATTEMPTS_KEY, (numberOfSessionAttempts + 1));
    817         ed.apply();
    818     }
    819 
    820     // check and initialize variables from preferences
    821     private boolean initFromSharedPreferences(Context context) {
    822         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    823         long timestamp = p.getLong(DMHelper.MESSAGE_TIMESTAMP_ID_KEY, -1);
    824         mUIMode = p.getInt(DMHelper.DM_UI_MODE_KEY, -1);
    825         mData = setDataFromFile(context);
    826         boolean success = !(timestamp <= 0 || mUIMode < 0);
    827         if (DBG) logd("initFromSharedPreferences: " + (success ? "ok" : "fail"));
    828         return success;
    829     }
    830 
    831     private static byte[] setDataFromFile(Context context) {
    832         SharedPreferences p = context.getSharedPreferences(DMHelper.DM_PREFERENCES_KEY, 0);
    833         int length = p.getInt("length", -1);
    834 
    835         if (length <= 0) {
    836             //logd("Error. Invalid postponed data length.");
    837             return null;
    838         }
    839 
    840         byte[] data = new byte[length];
    841 
    842         try {
    843             FileInputStream in = new FileInputStream(DMHelper.POSTPONED_DATA_PATH);
    844             if (in.read(data) <= 0) {
    845                 logd("Invalid postponed data.");
    846                 in.close();
    847                 return null;
    848             }
    849             in.close();
    850             return data;
    851         } catch (IOException e) {
    852             loge("IOException", e);
    853             return null;
    854         }
    855     }
    856 
    857     private static boolean treeExist(Context context) {
    858         if (context != null) {
    859             String strTreeHomeDir = context.getFilesDir().getAbsolutePath() + "/dm";
    860             File dirDes = new File(strTreeHomeDir);
    861 
    862             if (dirDes.exists() && dirDes.isDirectory()) {
    863                 logd("DM Tree exists:" + strTreeHomeDir);
    864                 return true;
    865             } else {
    866                 logd("DM Tree NOT exists:" + strTreeHomeDir);
    867                 return false;
    868             }
    869         } else {
    870             return false;
    871         }
    872     }
    873 
    874     // set current state
    875     private static void setFotaApnState(Context context, int state) {
    876         logd("setFotaApnState: " + state);
    877         SharedPreferences p = context.getSharedPreferences(DMHelper.FOTA_APN_PREFERENCE_KEY, 0);
    878         SharedPreferences.Editor ed = p.edit();
    879         ed.putInt(DMHelper.FOTA_APN_STATE_KEY, state);
    880         ed.apply();
    881     }
    882 
    883     // get current state.
    884     private static int getFotaApnState(Context context) {
    885         SharedPreferences p = context.getSharedPreferences(DMHelper.FOTA_APN_PREFERENCE_KEY, 0);
    886         return p.getInt(DMHelper.FOTA_APN_STATE_KEY, 0);
    887     }
    888 
    889     /**
    890      * Stop using the FOTA APN.
    891      * @param context the BroadcastReceiver context
    892      */
    893     private static void stopUsingFotaApn(Context context) {
    894         logd("stopUsingFotaApn");
    895 
    896         ConnectivityManager connMgr = (ConnectivityManager) context
    897                 .getSystemService(Context.CONNECTIVITY_SERVICE);
    898         int result = connMgr.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
    899                 Phone.FEATURE_ENABLE_FOTA);
    900         if (result != -1) {
    901             Log.w(TAG, "stopUsingNetworkFeature result=" + result);
    902         }
    903         stopDataConnectionService(context);
    904     }
    905 
    906     // Function which will send intents to start FDM
    907     private static void sendNotifyIntent(Context context) {
    908         logd("Inside sendNotifyIntent");
    909 
    910         SharedPreferences p = context.getSharedPreferences(DMHelper.FOTA_APN_PREFERENCE_KEY, 0);
    911         String lawmoResult = p.getString(DMHelper.LAWMO_RESULT_KEY, null);
    912         String fotaResult = p.getString(DMHelper.FOTA_RESULT_KEY, null);
    913         String pkgURI = p.getString(DMHelper.PKG_URI_KEY, null);
    914         String alertType = p.getString(DMHelper.ALERT_TYPE_KEY, null);
    915         String correlator = p.getString(DMHelper.CORRELATOR_KEY, null);
    916         String serverID = p.getString(DMHelper.SERVER_ID_KEY, null);
    917 
    918         logd("sendNotifyIntent Input==>\n" + " lawmoResult="
    919                 + lawmoResult + '\n' + "fotaResult="
    920                 + fotaResult + '\n' + " pkgURI="
    921                 + pkgURI + '\n' + " alertType="
    922                 + alertType + '\n' + " serverID="
    923                 + serverID + '\n' + " correlator="
    924                 + correlator);
    925 
    926         if (alertType.equals(ALERT_TYPE_DOWNLOADANDUPDATE)) {
    927             // Need to send an intent for doing a FOTA FDM session
    928             Intent fotafdmintent = new Intent(DMIntent.LAUNCH_INTENT);
    929             fotafdmintent.putExtra(DMIntent.FIELD_TYPE, DMIntent.TYPE_FOTA_NOTIFY_SERVER);
    930             fotafdmintent.putExtra(DMIntent.FIELD_FOTA_RESULT, fotaResult);
    931             fotafdmintent.putExtra(DMIntent.FIELD_PKGURI, pkgURI);
    932             fotafdmintent.putExtra(DMIntent.FIELD_ALERTTYPE, alertType);
    933             fotafdmintent.putExtra(DMIntent.FIELD_SERVERID, serverID);
    934             fotafdmintent.putExtra(DMIntent.FIELD_CORR, correlator);
    935             fotafdmintent.setClass(context, DMClientService.class);
    936             context.startService(fotafdmintent);
    937         } else if (pkgURI.equals(RP_OPERATIONS_FACTORYRESET) || pkgURI
    938                 .equals(RP_EXT_OPERATIONS_RESET)) {
    939             // LAWMO FDM session
    940             Intent lawmofdmintent = new Intent(DMIntent.LAUNCH_INTENT);
    941             lawmofdmintent.putExtra(DMIntent.FIELD_TYPE, DMIntent.TYPE_LAWMO_NOTIFY_SESSION);
    942             lawmofdmintent.putExtra(DMIntent.FIELD_LAWMO_RESULT, lawmoResult);
    943             lawmofdmintent.putExtra(DMIntent.FIELD_PKGURI, pkgURI);
    944             lawmofdmintent.putExtra(DMIntent.FIELD_ALERTTYPE, "");
    945             lawmofdmintent.putExtra(DMIntent.FIELD_CORR, "");
    946             lawmofdmintent.setClass(context, DMClientService.class);
    947             context.startService(lawmofdmintent);
    948         } else {
    949             // just return for now
    950             logd("No Action, Just return for now");
    951         }
    952     }
    953 
    954     private static boolean isWifiConnected(Context context) {
    955         logd("Inside isWifiConnected");
    956 
    957         ConnectivityManager cm = (ConnectivityManager) context
    958                 .getSystemService(Context.CONNECTIVITY_SERVICE);
    959         if (cm == null) {
    960             logd("can't get Connectivity Service");
    961             return false;
    962         }
    963 
    964         NetworkInfo ni = cm.getActiveNetworkInfo();
    965         if (ni == null) {
    966             logd("NetworkInfo is null");
    967             return false;
    968         }
    969         if (!ni.isConnected()) {
    970             logd("Network is not connected");
    971             return false;
    972         }
    973         if (ni.getType() != ConnectivityManager.TYPE_WIFI) {
    974             logd("network type is not wifi");
    975             return false;
    976         }
    977 
    978         // return true only when WiFi is connected
    979         return true;
    980     }
    981 
    982 
    983     private static boolean isPhoneTypeLTE() {
    984         return DMSettingsHelper.isPhoneTypeLTE();
    985     }
    986 
    987     private static boolean isPhoneTypeCDMA3G(Context context) {
    988         TelephonyManager tm = (TelephonyManager) context
    989                 .getSystemService(Context.TELEPHONY_SERVICE);
    990         if ((tm.getCurrentPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) && !isPhoneTypeLTE()) {
    991             logd("3G CDMA phone");
    992             return true;
    993         }
    994         logd("Non-CDMA or 4G Device");
    995         return false;
    996     }
    997 
    998     // check if we can set up a mobile data connection on this network type
    999     private static boolean isDataNetworkAcceptable(Context context) {
   1000         TelephonyManager tm = (TelephonyManager) context
   1001                 .getSystemService(Context.TELEPHONY_SERVICE);
   1002 
   1003         int callState = tm.getCallState();
   1004         if (callState != TelephonyManager.CALL_STATE_IDLE) {
   1005             logd("Call state not idle: " + callState);
   1006             return false;
   1007         }
   1008 
   1009         int dataNetworkType = tm.getDataNetworkType();
   1010         switch (dataNetworkType) {
   1011             case TelephonyManager.NETWORK_TYPE_EVDO_0:
   1012             case TelephonyManager.NETWORK_TYPE_EVDO_A:
   1013             case TelephonyManager.NETWORK_TYPE_1xRTT:
   1014             case TelephonyManager.NETWORK_TYPE_EVDO_B:
   1015             case TelephonyManager.NETWORK_TYPE_LTE:
   1016             case TelephonyManager.NETWORK_TYPE_EHRPD:
   1017                 logd("Data network type is acceptable: " + dataNetworkType);
   1018                 return true;
   1019 
   1020             default:
   1021                 logd("Data network type is not acceptable: " + dataNetworkType);
   1022                 return false;
   1023         }
   1024     }
   1025 
   1026     private static void saveDevDetail(Context context) {
   1027         logd("Inside saveDevDetail");
   1028 
   1029         String swVer = SystemProperties.get("ro.build.version.full");
   1030         if (TextUtils.isEmpty(swVer)) {
   1031             swVer = "Unknown";
   1032         }
   1033 
   1034         SharedPreferences p = context.getSharedPreferences(DEV_DETAIL, 0);
   1035         String currFwV = p.getString(CURR_FW_VER, null);
   1036         //String preFwV = p.getString(PRE_FW_VER, null);
   1037 
   1038         SharedPreferences.Editor ed = p.edit();
   1039         if (TextUtils.isEmpty(currFwV)) {
   1040             logd("First powerup or powerup after FDR, save current SwV");
   1041             ed.putString(CURR_FW_VER, swVer);
   1042         } else if (!(currFwV.equals(swVer))) {
   1043             logd("System Update success, save previous FwV and LastUpdateTime");
   1044             ed.putString(PRE_FW_VER, currFwV);
   1045             ed.putString(CURR_FW_VER, swVer);
   1046             SimpleDateFormat simpleDateFormat;
   1047             if (isPhoneTypeLTE()) {
   1048                 simpleDateFormat = new SimpleDateFormat("MM:dd:yyyy:HH:mm", Locale.US);
   1049                 simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
   1050             } else {
   1051                 simpleDateFormat = new SimpleDateFormat("MM:dd:yy:HH:mm:ss:z", Locale.US);
   1052             }
   1053             String currTime = simpleDateFormat.format(new Date(System.currentTimeMillis()));
   1054             ed.putString(LAST_UPD_TIME, currTime);
   1055         }
   1056         WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
   1057         WifiInfo wi = wm.getConnectionInfo();
   1058         String wMacAddr = (wi == null) ? null : wi.getMacAddress();
   1059         logd("WiFi Mac address " + wMacAddr);
   1060         if (!TextUtils.isEmpty(wMacAddr)) {
   1061             ed.putString(WIFI_MAC_ADDR, wMacAddr);
   1062         }
   1063         ed.apply();
   1064     }
   1065 
   1066     private static void logd(String msg) {
   1067         Log.d(TAG, msg);
   1068     }
   1069 
   1070     private static void loge(String msg) {
   1071         Log.e(TAG, msg);
   1072     }
   1073 
   1074     private static void loge(String msg, Throwable tr) {
   1075         Log.e(TAG, msg, tr);
   1076     }
   1077 }
   1078