com.android.server.MaybeService.java Source code

Java tutorial

Introduction

Here is the source code for com.android.server.MaybeService.java

Source

/* maybe We Should Enable More Uncertain Mobile App Programming
*  PhoneLab - phone-lab.org
*  <License info>
*  @author: Sriram Shantharam
*  
*/

/*
* ~List of TODOs/ Nice to have~
* 1. Sanitize all inputs like urls, json strings (partially done for JSONObjects)
* 2. Check for redundant correctness checks in MaybeService.java and MaybeDatabaseHelper.java
* 3. Maybe club all the Asynctasks into one?
*/

package com.android.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Binder;
import android.os.IMaybeService;
import android.os.RemoteException;
import android.util.Log;
import java.util.Calendar;
import java.text.SimpleDateFormat;
import android.content.Context;
import org.json.JSONObject;
import android.telephony.TelephonyManager;
import org.apache.http.*;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import java.io.OutputStream;
import org.apache.http.client.*;
import org.apache.http.impl.client.*;
import java.io.IOException;
import android.net.http.AndroidHttpClient;
import org.apache.http.client.methods.HttpGet;
import android.os.AsyncTask;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.JSONException;
import java.lang.Void;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Map.Entry;
import java.net.URLEncoder;
import java.io.UnsupportedEncodingException;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;
import java.net.URLEncoder;
import java.io.*;
import java.net.URL;
import java.net.HttpURLConnection;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.StringEntity;
import com.google.android.gms.common.*;
import com.google.android.gms.gcm.*; //Req Google Cloud Messaging  
import android.os.IMaybeListener;
import android.os.MaybeListener;
import android.content.SharedPreferences;
import android.net.NetworkInfo;
import java.util.TimerTask;
import java.util.Timer;
import java.util.Date;

public class MaybeService extends IMaybeService.Stub {
    private static final String TAG = "MaybeService";
    private static final String LOGTAG = "MaybeServiceLogging";
    private static final String URL = "https://maybe.xcv58.me/maybe-api-v1/devices";
    private static final String SHARED_PREFERENCES_NAME = "maybeServicePreferences";
    private static final String GCM_ID_KEY = "gcm_id";
    private static final String GCM_PROJECT_ID = "0";
    //Server Error Codes
    private static final String ERR_NO_RECORDS_FOUND = "No Record(s) Found";
    private static final String ERR_DUPLICATE_KEY = "E11000 duplicate key error index";
    private static final String ERR_GENERIC_ERROR = "Error";
    private static final String ERR_JSON_ERROR = "JSON parse error";
    private static final int STATUS_200OK = 200;
    private static final int STATUS_201CREATED = 201;
    private static final int STATUS_204NOCONTENT = 204;

    public static final String STRING_TYPE = "type";
    public static final String STRING_NAME = "name";
    public static final String STRING_LABELS = "labels";
    public static final String STRING_LABEL = "label";
    public static final String STRING_SCORE = "score";
    public static final String STRING_CHOICES = "choices";
    public static final String STRING_CHOICE = "choice";
    public static final String STRING_LOG = "log";
    public static final String STRING_BAD = "bad";
    public static final String STRING_LAST_CHOICE = "last_choice";

    private Context mContext;
    private String mJSONResponse;
    private String mJSONDownloadData;
    private boolean mHasResponse = false;
    private final MaybeDatabaseHelper mDbHelper;
    private static Object sNetworkCallLock = new Object();
    private static Object sDownloadLock = new Object();
    private boolean mIsDeviceRegistered = false;

    private String mDeviceMEID = null;
    private String mHashedMEID = null;
    private String mGCMId = null;
    private SharedPreferences mSharedPrefs;
    private Object mGCMLock = new Object();
    private long mPollInterval = 5; //in seconds
    private Timer mDataDownloadTimer = null;
    private TimerTask mDataDownloaderTask = null;

    public MaybeService(Context context) {
        super();
        if (context == null) {
            Log.e(TAG, "ERROR: context is null");
        }
        mContext = context;
        Log.i(TAG, "MaybeService Called context:" + mContext);

        //init Database
        mDbHelper = MaybeDatabaseHelper.getInstance(mContext);
        getDeviceMEID();
        Log.d(TAG, "Device MEID:" + mDeviceMEID);
        mSharedPrefs = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
        initializeTimerTask();

    }

    /*
      private void getGCMId(){
        if(checkPlayServices()){
          getRegistrationIdLocked();
        }else{
          mGCMId = "NULL";
        }
        
      }
        
        
        
      void getRegistrationIdLocked(){
        
        synchronized(mGCMLock){
          String gcmId = mSharedPrefs.getString(GCM_ID_KEY, "");
          if(gcmId.isEmpty()){
        
        
      GCMTask gcmTask = new GCMTask();
      gcmTask.execute(null, null, null);
      try{
        mGCMLock.wait();
       }catch(InterruptedException e){
          Log.e(TAG, "Exception while waiting for task");
          e.printStackTrace();
       }
        
          }else{
    mGCMId = gcmId;
          }
        }
        Log.i(TAG,"GCM ID:"+mGCMId);
        
      }
        
      class GCMTask extends AsyncTask<String, Void, String>{
        
        public GCMTask(){
        
        }
        
        @Override
        protected String doInBackground(String... params){
          GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(mContext);
        try {
            String regId = gcm.register(GCM_PROJECT_ID);
            // You should send the registration ID to your server over HTTP,
            // so it can use GCM/HTTP or CCS to send messages to your app.
            // The request to your server should be authenticated if your app
            // is using accounts.
            //TODO: maybe service should send this every time a new app registers
            // a new url
            //sendRegistrationIdToBackend();
            synchronized(mGCMLock){
                 
              SharedPreferences.Editor editor = mSharedPrefs.edit();
              editor.putString(GCM_ID_KEY, regId);
              editor.commit();
              mGCMId = regId;
              mGCMLock.notify();
        
                  
          }
        
              
        
        
        } catch (IOException e) {
            Log.e(TAG, "Exception while registering with GCM");
            e.printStackTrace();
                
        }
        return null;
        }
        
            
        
        @Override
        protected void onPostExecute(String result){
              
        }
        }
        
            
            
        
        
        
          
        
          
        
        
        
      private boolean checkPlayServices() {
          int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);
          if (resultCode != ConnectionResult.SUCCESS) {
      if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
          Log.i(TAG, "Google play services not installed");
      } else {
          Log.i(TAG, "This device is not supported.");
              
      }
      return false;
          }
          return true;
      }
    */
    private void initializeTimerTask() {

        mDataDownloadTimer = new Timer();
        mDataDownloaderTask = new TimerTask() {
            public void run() {
                Log.v(TAG, "Querying server");
                if (mIsDeviceRegistered) {
                    synchronized (sDownloadLock) {
                        String deviceMeid = getDeviceMEID();
                        if (deviceMeid == null) { // TelephonyManager not initialized
                            return;
                        }
                        String serverUrl = URL + "/" + deviceMeid;
                        new JSONDownloaderTask().execute(serverUrl);
                        try {
                            sDownloadLock.wait();
                            parseData(mJSONDownloadData);

                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } //end sync sDownloadLock
                } else {
                    synchronized (sNetworkCallLock) {

                        new DeviceRegisterTask().execute(URL);

                        try {
                            sNetworkCallLock.wait();
                            parseData(mJSONResponse);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                        Log.d(TAG, "Received data from TASK: " + mJSONResponse);

                    } //end sync sNetworkCallLock
                }
            }
        };
        mDataDownloadTimer.schedule(mDataDownloaderTask, 30000, (mPollInterval * 1000));
    }

    protected synchronized void parseData(String data) {
        if (data == null) {
            Log.i(TAG, "data is null");
            return;
        }
        try {
            //JSONObject jsonData = new JSONObject(data.trim());
            JSONArray jsonArray = MaybeUtils.getJSONArray(data);
            if (jsonArray == null) {
                Log.e(TAG, "Not a valid JSON Array");
                return;
            }
            JSONObject jsonData = jsonArray.getJSONObject(0); //one record for each device

            Log.v(TAG, "JsonData:" + jsonData.toString());
            JSONObject choiceData = jsonData.optJSONObject(STRING_CHOICES);
            Log.v(TAG, "Choices:" + choiceData.toString());
            Iterator<String> appHashKeys = choiceData.keys();
            while (appHashKeys.hasNext()) {
                String packageHash = (String) appHashKeys.next();
                Log.v(TAG, "Current packageHash:" + packageHash);
                JSONObject packageJSONObj = choiceData.optJSONObject(packageHash);
                String packageName = packageJSONObj.optString(STRING_NAME);
                Log.v(TAG, "Current packageName:" + packageName);
                JSONArray jsonArrayData = packageJSONObj.optJSONArray(STRING_LABELS);
                /* insert data into db */
                if (!mDbHelper.hasEntries(packageName)) {
                    mDbHelper.setUrl(packageName, URL);
                    mDbHelper.updateDataInDb(packageName, MaybeDatabaseHelper.HASH_COL, packageHash);
                }

                mDbHelper.updateDataInDb(packageName, MaybeDatabaseHelper.DATA_COL, jsonArrayData.toString());
                Log.i(TAG, jsonArrayData.toString());
                /* end insert data into db */
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    public void logTime(String message, long time1, long time2) {
        long interval = time2 - time1;
        if (interval < 0) {
            interval *= -1;
        }
        JSONObject timeObj = new JSONObject();
        try {
            timeObj.put("interval", interval);
            timeObj.put("message", message);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        Log.i(LOGTAG, timeObj.toString());
    }

    public Date tick() {
        return new Date();
    }

    public void tock(Date time1, JSONObject data) {
        Date time2 = new Date();
        long interval = time2.getTime() - time1.getTime();
        if (interval < 0) {
            interval *= -1;
        }
        JSONObject timeObj = new JSONObject();
        try {
            timeObj.put("interval", interval);
            timeObj.put("message", data);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        Log.i(LOGTAG, timeObj.toString());
    }

    public String getCurrentTime() throws RemoteException {
        Log.d(TAG, "Time" + ":getCurrentTime()");
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        Log.i(TAG, (sdf.format(cal.getTime())).toString());
        return (sdf.format(cal.getTime())).toString();
    }

    public void printCurrentTime() throws RemoteException {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        Log.i(TAG, (sdf.format(cal.getTime())).toString());
    }

    public int registerUrl(String pkgName, String url, String hash) throws RemoteException {
        //add to database
        //String packageName = getCallerPackageName();
        //temporary hack
        String packageName = pkgName;
        if (mDbHelper.hasEntries(packageName)) {
            String urlInDb = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.URL_COL, packageName);
            if (url.equals(urlInDb)) {
                return 0;
            } else {
                mDbHelper.updateDataInDb(packageName, MaybeDatabaseHelper.URL_COL, url);
            }
        } else {
            mDbHelper.setUrl(packageName, url);
            if (hash != null) {
                mDbHelper.updateDataInDb(packageName, MaybeDatabaseHelper.HASH_COL, hash);
            }

            synchronized (sNetworkCallLock) {

                new DeviceRegisterTask().execute(url, packageName, null);

                try {
                    sNetworkCallLock.wait();

                    parseData(mJSONResponse);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                Log.d(TAG, "Received data from TASK: " + mJSONResponse);

            }

        }

        return 1; // Error codes in future?
    }

    public int registerUrl(String url) throws RemoteException {
        //return registerUrl(null, url, null);
        return 0;
    }

    public int deletePackageData() {
        return mDbHelper.deletePackageInfo(getCallerPackageName());
    }

    private String getDeviceMEID() {
        if (mDeviceMEID == null) {
            TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
            mDeviceMEID = tm.getDeviceId();
            Log.d(TAG, "Device MEID:" + mDeviceMEID);
        }
        return mDeviceMEID;
    }

    /* testing only */
    public String getAppData(String pkgName) throws RemoteException {
        return null;
    }

    public void requestMaybeUpdates(String pkgName, String url, IMaybeListener listener) {

    }

    public void removeMaybeUpdates(String pkgName, IMaybeListener listener) {

    }

    public synchronized int getMaybeAlternative(String pkgName, String label) {
        Date tick = tick();
        //String packageName = getCallerPackageName();
        //temporary hack
        String packageName = pkgName;
        JSONObject jsonLog = new JSONObject();
        Log.v(TAG, "Calling package:" + packageName);
        String jsonData = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.DATA_COL, packageName);
        //JSONObject jsonObjData = MaybeUtils.getJSONObject(jsonData);

        if (jsonData == null) {
            Log.i(TAG, "jsondata is null");
            //TODO: Optimize logging for error scenarios

            try {
                jsonLog.put("function", "getMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("choice", "Error");
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "DBQUERY:NULL");
                tock(tick, jsonLog);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return -1;
        }

        String strChoice = MaybeUtils.parseJSONArray(label, jsonData);
        if (strChoice == null) {
            Log.i(TAG, "strchoice is null");
            //TODO: Optimize logging for error scenarios
            try {
                jsonLog.put("function", "getMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("choice", "Error");
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "JSON:NULL");
                tock(tick, jsonLog);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return -1;
        }

        int choice = Integer.parseInt(strChoice);
        Log.i(TAG, "choice: " + choice);

        try {
            jsonLog.put("function", "getMaybeAlternative");
            jsonLog.put("label", label);
            jsonLog.put("choice", choice);
            jsonLog.put("package", pkgName);

        } catch (JSONException e) {
            e.printStackTrace();
        }
        tock(tick, jsonLog);
        return choice;

    }

    public void badMaybeAlternative(String pkgName, String label, int value) {
        Date tick = tick();
        //String packageName = getCallerPackageName();
        //temporary hack
        JSONObject jsonLog = new JSONObject();
        String packageName = pkgName;
        //TODO: Needs improvement
        /*
        if(!MaybeUtils.isValidJSONString(jsonstring)){
          Log.e(TAG, "(1)Invalid JSON Object passed for scoring");
          return; //fail silently
        }
        */
        String url = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.URL_COL, packageName) + "/" + getDeviceMEID();
        if (url == null) {
            Log.e(TAG, "Server URL is null. Server url might not be registered with the service");
            try {
                jsonLog.put("function", "badMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("value", value);
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "URL:NULL");
                tock(tick, jsonLog);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            return;
        }
        String hash = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.HASH_COL, packageName);
        JSONObject scoreData = new JSONObject();
        try {
            scoreData.put(STRING_TYPE, STRING_BAD);
            scoreData.put(STRING_NAME, packageName);
            scoreData.put(label, value);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        new ServerUpdaterTask().execute(url, hash, scoreData.toString());

        try {
            jsonLog.put("function", "badMaybeAlternative");
            jsonLog.put("label", label);
            jsonLog.put("value", value);
            jsonLog.put("package", pkgName);
            tock(tick, jsonLog);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return; //if JSONException fail silently
    }

    /*
      {
        
      }
    */
    public void scoreMaybeAlternative(String pkgName, String label, String jsonString) {
        Date tick = tick();
        JSONObject jsonLog = new JSONObject();
        //String packageName = getCallerPackageName();
        //temporary hack
        String packageName = pkgName;
        //TODO: Needs improvement
        if (!MaybeUtils.isValidJSONString(jsonString)) {
            Log.e(TAG, "(1)Invalid JSON Object passed for scoring");
            try {
                jsonLog.put("function", "scoreMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("value", jsonString);
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "JSON:INVALID");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            tock(tick, jsonLog);
            return; //fail silently
        }
        String url = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.URL_COL, packageName) + "/" + getDeviceMEID();
        if (url == null) {
            Log.e(TAG, "Server URL is null. Server url might not be registered with the service");
            try {
                jsonLog.put("function", "scoreMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("value", jsonString);
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "URL:NULL");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            tock(tick, jsonLog);
            return;
        }
        String hash = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.HASH_COL, packageName);
        JSONObject scoreData = new JSONObject();
        try {
            scoreData.put(STRING_TYPE, STRING_SCORE);
            scoreData.put(STRING_NAME, packageName);
            scoreData.put(label, jsonString);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        new ServerUpdaterTask().execute(url, hash, scoreData.toString());

        try {
            jsonLog.put("function", "scoreMaybeAlternative");
            jsonLog.put("label", label);
            jsonLog.put("value", jsonString);
            jsonLog.put("package", pkgName);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        tock(tick, jsonLog);
        return; //if JSONException fail silently
    }

    public void logMaybeAlternative(String pkgName, String label, String jsonString) {
        Date tick = tick();
        JSONObject jsonLog = new JSONObject();
        //String packageName = getCallerPackageName();
        //temporary hack
        String packageName = pkgName;

        String lastChoice = null;

        if (!MaybeUtils.isValidJSONString(jsonString)) {
            Log.e(TAG, "(1)Invalid JSON Object passed for scoring");

            try {
                jsonLog.put("function", "logMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("value", jsonString);
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "JSON:INVALID");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            tock(tick, jsonLog);

            return; //fail silently
        }
        String url = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.URL_COL, packageName) + "/" + getDeviceMEID();
        if (url == null) {
            Log.e(TAG, "Server URL is null. Server url might not be registered with the service");

            try {
                jsonLog.put("function", "logMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("value", jsonString);
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "URL:NULL");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            tock(tick, jsonLog);

            return;
        }
        //TODO: How do we ensure data hasn't changed since last call?
        String jsonData = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.DATA_COL, packageName);
        if (jsonData == null) {
            Log.i(TAG, "jsondata is null");

            try {
                jsonLog.put("function", "logMaybeAlternative");
                jsonLog.put("label", label);
                jsonLog.put("value", jsonString);
                jsonLog.put("package", pkgName);
                jsonLog.put("Error", "JSON:NULL");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            tock(tick, jsonLog);

            return;
        } else {

            lastChoice = MaybeUtils.parseJSONArray(label, jsonData);
            if (lastChoice == null) {
                Log.i(TAG, "lastChoice is null");
                try {
                    jsonLog.put("function", "logMaybeAlternative");
                    jsonLog.put("label", label);
                    jsonLog.put("value", jsonString);
                    jsonLog.put("package", pkgName);
                    jsonLog.put("Error", "CHOICE:NULL");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                tock(tick, jsonLog);
                return;
            }
        }
        String hash = mDbHelper.getAppDataFromDb(MaybeDatabaseHelper.HASH_COL, packageName);

        JSONObject logData = new JSONObject();
        try {
            logData.put(STRING_TYPE, STRING_LOG);
            logData.put(STRING_NAME, packageName);
            logData.put(STRING_LAST_CHOICE, lastChoice);
            logData.put(label, jsonString);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        new ServerUpdaterTask().execute(url, hash, logData.toString());

        try {
            jsonLog.put("function", "logMaybeAlternative");
            jsonLog.put("label", label);
            jsonLog.put("value", jsonString);
            jsonLog.put("package", pkgName);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        tock(tick, jsonLog);
        return;

    }

    private String getCallerPackageName() {
        return mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
    }

    /* HTTP post 
    * @deprecated
    */

    class JSONDownloaderTask extends AsyncTask<String, Void, String> {
        HttpClient client;

        public JSONDownloaderTask() {
            client = new DefaultHttpClient();

        }

        @Override
        protected String doInBackground(String... params) {
            String networkResponse = null;
            try {

                HttpGet geturl = new HttpGet(params[0]);
                geturl.setHeader("Content-type", "application/json");

                HttpResponse response = client.execute(geturl);
                int statusCode = response.getStatusLine().getStatusCode();
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                networkResponse = out.toString();
                //TODO:
                Log.d(TAG, networkResponse);
                if (networkResponse.contains(ERR_NO_RECORDS_FOUND)) {
                    Log.d(TAG, "No Records found");
                    // Keep the error and parse it at the timer task. Register the device if
                    // this is the case.
                    mIsDeviceRegistered = false;
                    //networkResponse = null; 
                } else {
                    Log.d(TAG, "update exists");
                    //TODO: (?)

                }
                out.close();

            } catch (IOException e) {
                Log.v(TAG, "(1)JSON Downloader Task exception: check network connectivity");
                e.printStackTrace();
            } catch (Exception e) {
                Log.v(TAG, "(2)JSON Downloader Task exception: check network connectivity");
                e.printStackTrace();
            }

            return networkResponse;
        }

        @Override
        protected void onPostExecute(String result) {
            synchronized (sDownloadLock) {
                mJSONDownloadData = result;
                sDownloadLock.notify();
            }
        }

    }

    class ServerUpdaterTask extends AsyncTask<String, Void, String> {
        HttpClient client;

        public ServerUpdaterTask() {
            client = new DefaultHttpClient();

        }

        @Override
        protected String doInBackground(String... params) {
            // params[0]- url, params[1] - package name , params[2] - data in JSONString format
            String networkResponse = "";
            ByteArrayOutputStream out = null;
            Log.v(TAG, "url:" + params[0] + " packagename:" + params[1] + " data:" + params[2]);
            try {

                HttpPut putUrl = new HttpPut(params[0]);
                putUrl.setHeader("Content-type", "application/json");
                /*
                JSONObject data = new JSONObject();
                data.put(params[1],params[2]); 
                */
                JSONObject data = MaybeUtils.getJSONObject(params[2]);
                JSONObject labelData = new JSONObject();
                labelData.put(params[1], data);
                JSONObject postData = new JSONObject();
                postData.put("$set", labelData);
                StringEntity se = new StringEntity(postData.toString());
                putUrl.setEntity(se);
                HttpResponse response = client.execute(putUrl);
                //StatusLine statusLine = response.getStatusLine();
                out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                networkResponse = out.toString();
                int statusCode = response.getStatusLine().getStatusCode();
                Log.d(TAG, "Network response|status code:" + networkResponse + statusCode);
                if (statusCode == STATUS_204NOCONTENT || statusCode == STATUS_201CREATED
                        || statusCode == STATUS_200OK) {
                    networkResponse = out.toString();
                } else {
                    networkResponse = ERR_GENERIC_ERROR;
                }

            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {

                if (out != null) {
                    try {
                        out.close();
                        out = null;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }

            return networkResponse;
        }

        // Don't really need this at present, use in case we need it in future
        // to display toasts/message to the user in case of failures
        @Override
        protected void onPostExecute(String result) {
            String packageName = getCallerPackageName();
            if (result.contains(ERR_DUPLICATE_KEY) || result.contains(ERR_GENERIC_ERROR)) {
                Log.v(TAG, "Error while updating data to server");
                return;
            }

        }

    }

    class DeviceRegisterTask extends AsyncTask<String, Void, String> {
        HttpClient client;

        public DeviceRegisterTask() {
            client = new DefaultHttpClient();

        }

        @Override
        protected String doInBackground(String... params) {
            String networkResponse = null;
            ByteArrayOutputStream out = null;
            try {

                HttpPost posturl = new HttpPost(params[0]);
                posturl.setHeader("Content-type", "application/json");

                JSONObject data = new JSONObject();
                String meid = getDeviceMEID();
                data.put("deviceid", meid);
                StringEntity se = new StringEntity(data.toString());
                posturl.setEntity(se);
                HttpResponse response = client.execute(posturl);
                //StatusLine statusLine = response.getStatusLine();
                out = new ByteArrayOutputStream();
                response.getEntity().writeTo(out);
                int statusCode = response.getStatusLine().getStatusCode();
                String networkResponseString = out.toString();
                Log.v(TAG, "networkResponseString:" + networkResponseString);
                if (statusCode == STATUS_204NOCONTENT || statusCode == STATUS_201CREATED
                        || statusCode == STATUS_200OK) {
                    Log.v(TAG, "Device Register Status code: 2xx ");
                    networkResponse = networkResponseString;
                    mIsDeviceRegistered = true;
                } else {
                    if (networkResponseString.contains(ERR_DUPLICATE_KEY)) {
                        //networkResponse = networkResponseString;
                        mIsDeviceRegistered = true;
                    } else {
                        Log.d(TAG, "Network error:" + networkResponseString);
                        //networkResponse = ERR_GENERIC_ERROR;

                    }
                }

                Log.d(TAG, "Network response:" + networkResponse);
                if (out != null) {
                    out.close();
                    out = null;
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {

            }

            return networkResponse;
        }

        // Don't really need this at present, use in case we need it in future
        // to display toasts/message to the user in case of failures
        @Override
        protected void onPostExecute(String result) {

            Log.v(TAG, "DeviceRegisterTask nw data received" + result);
            /*
            if(result.contains(ERR_DUPLICATE_KEY) || result.contains(ERR_GENERIC_ERROR)){
              return;
            }
            */

            synchronized (sNetworkCallLock) {
                /*
                if(mDbHelper.hasEntries(packageName)){
                  mDbHelper.updateDataInDb(packageName, MaybeDatabaseHelper.DATA_COL, result);
                }
                */
                mJSONResponse = result;
                sNetworkCallLock.notify();
            }
        }

    }

    /* Test suite */

    private void dbTest() {

    }

    private void networkQueryTest() {

    }

    private void cacheTest() {

    }

}