@Override
  public int onStartCommand(Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);
    Utility.checkSelfAllPermissions(this);
    if (!Utility.hasPermission(Utility.PERMISSION_COARSE_LOCATION)
        && !Utility.hasPermission(Utility.PERMISSION_FINE_LOCATION)) {
      if (mHandler != null) mHandler.sendEmptyMessage(MSG_STOP_SELF);
      return START_NOT_STICKY;
    }

    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

    if (DEBUG) Log.d(TAG, "Service has received start id " + startId + ": " + intent);
    mReturnAddress = intent.getStringExtra("return_address");
    if (mReturnAddress == null || mReturnAddress.isEmpty()) {
      Log.e(TAG, "Lack return address");
      return START_NOT_STICKY;
    }

    mPrecise = intent.getIntExtra("precise", 10);
    mTrack = intent.getIntExtra("track", 1);

    if (mPrecise <= 0) mPrecise = 1;
    if (mPrecise >= 20) mPrecise = 20;
    if (mTrack <= 0) mTrack = 1;
    else if ((mTrack * mPrecise) > 240) mTrack = 240 / mPrecise;
    if (DEBUG) Log.d(TAG, "Precise " + mPrecise + ", Track " + mTrack);

    mReceiver = new MyReceiver();
    IntentFilter filter = new IntentFilter(Utility.ACTION_STOP_BACKGROUND);
    registerReceiver(mReceiver, filter);

    synchronized (mLock) {
      if (mThread != null) return START_NOT_STICKY;
      mThread = new HandlerThread("H1");
      mThread.start();
      mStartTime = 0;
      if (DEBUG) Log.d(TAG, "thread started");
      mHandler = new Handler(mThread.getLooper(), this);
      mHandler.sendEmptyMessage(MSG_GET_LOCATION);

      // Need keep wake until the location is updated.
      if (Utility.hasPermission(Utility.PERMISSION_WAKE_LOCK)) {
        mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WRU");
        mWakelock.acquire();
      }

      doReportStart();
    }
    // We want this service to continue running until it is explicitly
    // stopped, so return sticky.
    return START_STICKY;
  }
 @Override
 public boolean handleMessage(Message msg) {
   if (DEBUG) Log.d(TAG, "Message what: " + msg.what);
   int what = msg.what;
   LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
   switch (what) {
     case MSG_REPORT_COARSE_LOCATION:
       if (mNetworkLocation != null) doReportLocation(mNetworkLocation);
       return true;
     case MSG_REPORT_LOCATION:
       if (DEBUG) Log.d(TAG, "Track left " + mTrack);
       if (mLocation != null) doReportLocation(mLocation);
       if (--mTrack <= 0) {
         locationManager.removeUpdates(this);
         // Let AsyncTask finish
         mHandler.removeMessages(MSG_STOP_SELF);
         mHandler.sendEmptyMessageDelayed(MSG_STOP_SELF, 5000);
       }
       return true;
     case MSG_GET_LOCATION:
       if (Utility.hasPermission(Utility.PERMISSION_FINE_LOCATION))
         locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1, 4, this);
       if (Utility.hasPermission(Utility.PERMISSION_COARSE_LOCATION))
         locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1, 4, this);
       mHandler.sendEmptyMessageDelayed(MSG_STOP_SELF, STOP_SELF_DELAY);
       return true;
     case MSG_STOP_SELF:
       locationManager.removeUpdates(this);
       synchronized (mLock) {
         mHandler = null;
         if (mThread != null) mThread.quit();
         mThread = null;
       }
       doReportFinish();
       return true;
   }
   return false;
 }
  @Override
  public void onDestroy() {
    if (DEBUG) Log.d(TAG, "onDestroy()");
    mNetworkLocation = null;
    mLocation = null;
    mReportCounts = 0;
    mTrack = 0;
    mPrecise = 0;

    synchronized (mLock) {
      if (mReceiver != null) unregisterReceiver(mReceiver);
      mReceiver = null;
      mHandler = null;
      if (mThread != null) mThread.quit();
      mThread = null;
      if (Utility.hasPermission(Utility.PERMISSION_WAKE_LOCK)) {
        if (mWakelock != null) mWakelock.release();
        mWakelock = null;
      }
    }
  }