Merge "FMRecord: Add support for other languages"
diff --git a/FMRecord/src/com/codeaurora/fmrecording/FMRecordingService.java b/FMRecord/src/com/codeaurora/fmrecording/FMRecordingService.java
index 4657e36..3fb6446 100644
--- a/FMRecord/src/com/codeaurora/fmrecording/FMRecordingService.java
+++ b/FMRecord/src/com/codeaurora/fmrecording/FMRecordingService.java
@@ -61,7 +61,6 @@
 public class FMRecordingService extends Service {
     private static final String TAG     = "FMRecordingService";
     private BroadcastReceiver mFmRecordingReceiver = null;
-    private BroadcastReceiver mSdcardUnmountReceiver = null;
     public static final long UNAVAILABLE = -1L;
     public static final long PREPARING = -2L;
     public static final long UNKNOWN_SIZE = -3L;
@@ -84,7 +83,6 @@
         super.onCreate();
         Log.d(TAG, "FMRecording Service onCreate");
         registerRecordingListner();
-        registerExternalStorageListener();
     }
 
     public int onStartCommand(Intent intent, int flags, int startId) {
@@ -100,7 +98,6 @@
             stopRecord();
         }
         unregisterBroadCastReceiver(mFmRecordingReceiver);
-        unregisterBroadCastReceiver(mSdcardUnmountReceiver);
         super.onDestroy();
     }
 
@@ -116,38 +113,6 @@
            myreceiver = null;
        }
    }
-    /**
-      * Registers an intent to listen for ACTION_MEDIA_UNMOUNTED notifications.
-      * The intent will call closeExternalStorageFiles() if the external media
-      * is going to be ejected, so applications can clean up.
-      */
-    private void registerExternalStorageListener() {
-        if (mSdcardUnmountReceiver == null) {
-            mSdcardUnmountReceiver = new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    String action = intent.getAction();
-                    if ((action.equals(Intent.ACTION_MEDIA_UNMOUNTED))
-                         || (action.equals(Intent.ACTION_MEDIA_EJECT))) {
-
-                         Log.d(TAG, "ACTION_MEDIA_UNMOUNTED Intent received");
-                         if (mFmRecordingOn == true) {
-                             try {
-                                  stopRecord();
-                             } catch (Exception e) {
-                                  e.printStackTrace();
-                             }
-                         }
-                    }
-                }
-            };
-            IntentFilter iFilter = new IntentFilter();
-            iFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
-            iFilter.addAction(Intent.ACTION_MEDIA_EJECT);
-            iFilter.addDataScheme("file");
-            registerReceiver(mSdcardUnmountReceiver, iFilter);
-        }
-    }
 
     private static long getAvailableSpace() {
         String state = Environment.getExternalStorageState();
diff --git a/fmapp2/res/menu/menu_rf_stats.xml b/fmapp2/res/menu/menu_rf_stats.xml
new file mode 100644
index 0000000..505e49b
--- /dev/null
+++ b/fmapp2/res/menu/menu_rf_stats.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     * Copyright (c) 2013 The Linux Foundation. All rights reserved.
+     *
+     * Redistribution and use in source and binary forms, with or without
+     * modification, are permitted provided that the following conditions are met:
+     *    * Redistributions of source code must retain the above copyright
+     *      notice, this list of conditions and the following disclaimer.
+     *    * Redistributions in binary form must reproduce the above copyright
+     *      notice, this list of conditions and the following disclaimer in the
+     *      documentation and/or other materials provided with the distribution.
+     *    * Neither the name of The Linux Foundation nor
+     *      the names of its contributors may be used to endorse or promote
+     *      products derived from this software without specific prior written
+     *      permission.
+     *
+     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+     * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+     * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+     * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/menu_recording"
+        android:icon="@drawable/ic_menu_record"
+        android:showAsAction="ifRoom|withText" />
+
+    <item android:id="@+id/menu_record_duration"
+        android:showAsAction="ifRoom|withText"
+        android:title=""/>
+
+</menu>
+
diff --git a/fmapp2/src/com/caf/fmradio/CommaSeparatedFreqFileReader.java b/fmapp2/src/com/caf/fmradio/CommaSeparatedFreqFileReader.java
new file mode 100644
index 0000000..df1b67d
--- /dev/null
+++ b/fmapp2/src/com/caf/fmradio/CommaSeparatedFreqFileReader.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *            notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.caf.fmradio;
+
+import android.util.Log;
+
+import java.io.*;
+
+public class CommaSeparatedFreqFileReader implements GetNextFreqInterface {
+
+   private BufferedReader reader;
+   private String fileName;
+   private String [] freqList;
+   private int index;
+   private static final String LOGTAG = "COMMA_SEPARATED_FREQ_PARSER";
+   private boolean errorHasOcurred;
+
+   @Override
+   public int getNextFreq() {
+      int freq = Integer.MAX_VALUE;
+
+      Log.d(LOGTAG, "Inside function get freq");
+      if(!errorHasOcurred) {
+         if(index < freqList.length) {
+            try {
+                freq = (int)(Float.parseFloat(freqList[index]) * 1000);
+            }catch(NumberFormatException e) {
+                Log.d(LOGTAG, "Format exception");
+            }
+            index++;
+            if(index >= freqList.length) {
+               index = 0;
+               readLineAndParse();
+            }
+            return freq;
+         }else {
+            return Integer.MAX_VALUE;
+         }
+      }else {
+         return Integer.MAX_VALUE;
+      }
+   }
+
+   public CommaSeparatedFreqFileReader(String fileName) {
+      this.fileName = fileName;
+      try {
+           reader =  new BufferedReader(new FileReader(this.fileName));
+           readLineAndParse();
+      }catch(Exception e) {
+           errorHasOcurred = true;
+           Log.d(LOGTAG, "File not found");
+      }
+   }
+
+   private void readLineAndParse() {
+      String curLine;
+      if(reader != null) {
+         try {
+              if((curLine = reader.readLine()) != null) {
+                 freqList = curLine.split(",");
+              }else {
+                 reader.close();
+                 reader = null;
+                 errorHasOcurred = true;
+              }
+         }catch(Exception e) {
+              errorHasOcurred = true;
+         }
+      }else {
+         errorHasOcurred = true;
+      }
+   }
+
+   @Override
+   public void Stop() {
+      if(reader != null) {
+         try {
+             reader.close();
+             reader = null;
+         }catch(Exception e) {
+         }
+         errorHasOcurred = true;
+      }
+   }
+
+   @Override
+   public boolean errorOccured() {
+      return errorHasOcurred;
+   }
+}
+
diff --git a/fmapp2/src/com/caf/fmradio/FMRadio.java b/fmapp2/src/com/caf/fmradio/FMRadio.java
index 631ab40..e311172 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadio.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadio.java
@@ -460,7 +460,7 @@
               }
           }
       }
-      if(isRecordTimerActive()) {
+      if(isRecording()) {
           try {
               if (null != mRecordUpdateHandlerThread) {
                   mRecordUpdateHandlerThread.interrupt();
@@ -468,17 +468,6 @@
           }catch (NullPointerException e) {
               e.printStackTrace();
           }
-          long rtimeNow = ((SystemClock.elapsedRealtime()));
-          if (rtimeNow < mRecordDuration) {
-              try {
-                if (null != mService) {
-                    mService.delayedStop((mRecordDuration - rtimeNow),
-                                              FMRadioService.STOP_RECORD);
-                }
-              }catch (Exception e) {
-                e.printStackTrace();
-              }
-          }
       }
       super.onStop();
    }
@@ -505,8 +494,8 @@
           }
           initiateSleepThread();
       }
-      if(isRecordTimerActive()) {
-          Log.d(LOGTAG, "isRecordTimerActive is true");
+      if(isRecording()) {
+          Log.d(LOGTAG,"isRecordTimerActive is true");
           try {
             if (null != mService) {
                 mService.cancelDelayedStop(FMRadioService.STOP_RECORD);
@@ -774,66 +763,35 @@
    private static final int RECORDTIMER_EXPIRED = 0x1003;
    private static final int RECORDTIMER_UPDATE = 0x1004;
 
-   private boolean hasRecordTimerExpired() {
-      boolean expired = true;
-      /* If record duration is 'until stopped' then return false and exit */
-      if (mRecordUntilStopped)
-          return false;
-      if (isRecordTimerActive()) {
-         long timeNow = ((SystemClock.elapsedRealtime()));
-         //Log.d(LOGTAG, "hasSleepTimerExpired - " + mSleepAtPhoneTime + " now: "+ timeNow);
-         if ((mRecording == false) || (timeNow < mRecordDuration)) {
-             expired = false;
-         }
-      }
-      return expired;
-   }
-
-   private boolean isRecordTimerActive() {
-      boolean active = false;
-      if (mRecordDuration > 0) {
-          active = true;
-      }
-      return active;
-   }
-
    private void updateExpiredRecordTime() {
       int vis = View.VISIBLE;
-      if (mRecordUntilStopped || isRecordTimerActive()) {
+      if(isRecording())
+      {
          long timeNow = ((SystemClock.elapsedRealtime()));
-         if (mRecordUntilStopped || (mRecordDuration >= timeNow)) {
-            long seconds = (timeNow - mRecordStartTime) / 1000;
-            String Msg = makeTimeString(seconds);
-            mRecordingMsgTV.setText(Msg);
-         }else {
-            /* Clean up timer */
-            mRecordDuration = 0;
-         }
+         long seconds = (timeNow - getRecordingStartTime()) / 1000;
+         String Msg = makeTimeString(seconds);
+         mRecordingMsgTV.setText(Msg);
+         mRecordingMsgTV.setVisibility(vis);
       }
-      mRecordingMsgTV.setVisibility(vis);
    }
 
    /* Recorder Thread processing */
    private Runnable doRecordProcessing = new Runnable() {
       public void run() {
-         boolean recordTimerExpired;
-         if (mRecordUntilStopped) {
-             recordTimerExpired = false;
-         }else {
-             recordTimerExpired = hasRecordTimerExpired();
-         }
-         while ((recordTimerExpired == false) &&
-                  (!Thread.currentThread().isInterrupted())) {
-            try {
-                Thread.sleep(500);
-                Message statusUpdate = new Message();
-                statusUpdate.what = RECORDTIMER_UPDATE;
-                mUIUpdateHandlerHandler.sendMessage(statusUpdate);
-                recordTimerExpired = hasRecordTimerExpired();
-            }catch (InterruptedException e) {
-                Thread.currentThread().interrupt();
+         while (isRecording() &&
+                 (!Thread.currentThread().isInterrupted()))
+         {
+            try
+            {
+               Thread.sleep(500);
+               Message statusUpdate = new Message();
+               statusUpdate.what = RECORDTIMER_UPDATE;
+               mUIUpdateHandlerHandler.sendMessage(statusUpdate);
+            } catch (InterruptedException e)
+            {
+               Thread.currentThread().interrupt();
             }
-            if(true == recordTimerExpired) {
+            if(!isRecording()) {
                Message finished = new Message();
                finished.what = RECORDTIMER_EXPIRED;
                mUIUpdateHandlerHandler.sendMessage(finished);
@@ -842,24 +800,22 @@
       }
    };
 
-   private static long mRecordDuration = 0;
-   private static long mRecordStartTime = 0;
-   private static boolean mRecordUntilStopped = false;
    private Thread mRecordUpdateHandlerThread = null;
 
-   private void initiateRecordDurationTimer(long mins) {
+   private long getRecordingStartTime() {
 
-      if(mins == FmSharedPreferences.RECORD_DUR_INDEX_3_VAL) {
-          mRecordUntilStopped = true;
-          mRecordStartTime = SystemClock.elapsedRealtime();
-      }else {
-          mRecordUntilStopped = false;
-          mRecordDuration = (mRecordStartTime = SystemClock.elapsedRealtime())
-                                   +
-                            (mins * 60 * 1000);
+      if(mService == null)
+         return 0;
+
+      try {
+           return mService.getRecordingStartTime();
+      }catch(RemoteException e) {
+           return 0;
       }
+   }
 
-      Log.d(LOGTAG, "Stop Recording in mins: " + mins);
+   private void initiateRecordDurationTimer(long mins ) {
+      Log.d(LOGTAG, "Stop Recording in mins : " + mins);
       initiateRecordThread();
     }
     private void initiateRecordThread() {
@@ -1775,11 +1731,27 @@
       }
    }
 
+   private void setRecordingStopImage() {
+       if(null != mRecordingMsgTV) {
+          mRecordingMsgTV.setCompoundDrawablesWithIntrinsicBounds
+                           (R.drawable.recorder_stop, 0, 0, 0);
+       }
+   }
+
+   private void setRecordingStartImage() {
+       if(null != mRecordingMsgTV) {
+          mRecordingMsgTV.setCompoundDrawablesWithIntrinsicBounds
+                           (R.drawable.recorder_start, 0, 0, 0);
+       }
+   }
+
    private void startRecordingTimer() {
       mRecording = true;
       int durationInMins = FmSharedPreferences.getRecordDuration();
       Log.e(LOGTAG, " Fected duration:" + durationInMins );
       initiateRecordDurationTimer( durationInMins );
+      setRecordingStopImage();
+      invalidateOptionsMenu();
    }
 
    private void stopRecording() {
@@ -1790,8 +1762,7 @@
        }
        if(null != mRecordingMsgTV) {
           mRecordingMsgTV.setText("");
-          mRecordingMsgTV.setCompoundDrawablesWithIntrinsicBounds
-                           (R.drawable.recorder_start, 0, 0, 0);
+          setRecordingStartImage();
        }
        if (mService != null) {
            try {
@@ -1800,7 +1771,7 @@
               e.printStackTrace();
            }
         }
-        mRecordDuration = 0;
+        invalidateOptionsMenu();
    }
 
    private boolean isRecording() {
@@ -1874,6 +1845,11 @@
          if ((mRecordingMsgTV != null) && !isRecording()) {
              mRecordingMsgTV.setText("");
          }
+         if(isRecording()) {
+            setRecordingStopImage();
+         }else {
+            setRecordingStartImage();
+         }
       }else {
          if (mRadioTextScroller != null) {
              mRadioTextScroller.stopScroll();
@@ -2376,13 +2352,11 @@
             }
          case RECORDTIMER_EXPIRED: {
                Log.d(LOGTAG, "mUIUpdateHandlerHandler - RECORDTIMER_EXPIRED");
-               mRecordDuration = 0;
                //Clear the Recorder text
                mRecordingMsgTV.setText("");
                if (mRecording != false) {
                   DebugToasts("Stop Recording", Toast.LENGTH_SHORT);
                   stopRecording();
-                  invalidateOptionsMenu();
                }
               return;
             }
@@ -2921,16 +2895,7 @@
                e.printStackTrace();
             }
             if (isRecording()) {
-                mRecordingMsgTV.setCompoundDrawablesWithIntrinsicBounds
-                                  (R.drawable.recorder_stop, 0, 0, 0);
                 initiateRecordThread();
-            }else if((mRecordDuration > 0) &&
-                      (mRecordUpdateHandlerThread != null)) {
-                mRecordUpdateHandlerThread.interrupt();
-                if(mRecordingMsgTV != null) {
-                   mRecordingMsgTV.setText("");
-                }
-                mRecordDuration = 0;
             }
             return;
          }else {
diff --git a/fmapp2/src/com/caf/fmradio/FMRadioService.java b/fmapp2/src/com/caf/fmradio/FMRadioService.java
index a0df1ef..5dfe72d 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadioService.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadioService.java
@@ -294,6 +294,7 @@
                          if (state == RECORD_START) {
                              Log.d(LOGTAG, "FM Recording started");
                              mFmRecordingOn = true;
+                             mSampleStart = SystemClock.elapsedRealtime();
                              try {
                                   if ((mServiceInUse) && (mCallbacks != null) ) {
                                       Log.d(LOGTAG, "start recording thread");
@@ -312,6 +313,7 @@
                              } catch (RemoteException e) {
                                   e.printStackTrace();
                              }
+                             mSampleStart = 0;
                         }
                      }
                  }
@@ -688,6 +690,14 @@
    private void sendRecordIntent(int action) {
        Intent intent = new Intent(ACTION_FM_RECORDING);
        intent.putExtra("state", action);
+       if(action == RECORD_START) {
+          int mRecordDuration = -1;
+          if(FmSharedPreferences.getRecordDuration() !=
+             FmSharedPreferences.RECORD_DUR_INDEX_3_VAL) {
+             mRecordDuration = (FmSharedPreferences.getRecordDuration() * 60 * 1000);
+          }
+          intent.putExtra("record_duration", mRecordDuration);
+        }
        Log.d(LOGTAG, "Sending Recording intent for = " +action);
        getApplicationContext().sendBroadcast(intent);
    }
@@ -1469,6 +1479,10 @@
       {
            return (mService.get().setRxRepeatCount(count));
       }
+      public long getRecordingStartTime()
+      {
+           return (mService.get().getRecordingStartTime());
+      }
    }
    private final IBinder mBinder = new ServiceStub(this);
 
@@ -2929,6 +2943,9 @@
          return false;
    }
 
+   public long getRecordingStartTime() {
+      return mSampleStart;
+   }
    //handling the sleep and record stop when FM App not in focus
    private void delayedStop(long duration, int nType) {
        int whatId = (nType == STOP_SERVICE) ? STOPSERVICE_ONSLEEP: STOPRECORD_ONTIMEOUT;
diff --git a/fmapp2/src/com/caf/fmradio/FMStats.java b/fmapp2/src/com/caf/fmradio/FMStats.java
index e587c08..18ab71c 100644
--- a/fmapp2/src/com/caf/fmradio/FMStats.java
+++ b/fmapp2/src/com/caf/fmradio/FMStats.java
@@ -59,6 +59,16 @@
 import android.app.Dialog;
 import android.view.LayoutInflater;
 import android.content.DialogInterface;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.IntentFilter;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuInflater;
+import android.os.SystemClock;
 
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -68,6 +78,8 @@
 import android.os.SystemProperties;
 import java.io.BufferedReader;
 import java.io.FileReader;
+import java.util.Formatter;
+import java.util.Locale;
 
 public class FMStats extends Activity  {
 
@@ -89,6 +101,7 @@
       public int lFreq;
       public int hFreq;
       public int Spacing;
+      public int cur_freq;
     }
     /* Data structure for Result*/
     private class Result {
@@ -169,6 +182,8 @@
     private Thread mMultiUpdateThread = null;
     private static final int STATUS_UPDATE = 1;
     private static final int STATUS_DONE = 2;
+    private static final int RECORDTIMER_UPDATE = 3;
+    private static final int RECORDTIMER_EXPIRED = 4;
     private static final int STOP_ROW_ID = 200;
     private static final int NEW_ROW_ID = 300;
     private int mStopIds = STOP_ROW_ID;
@@ -222,7 +237,27 @@
 
     private int curSweepMthd = 0;
 
+    private Thread mRecordUpdateHandlerThread = null;
+    boolean mRecording = false;
+
+
+    private static StringBuilder sFormatBuilder = new StringBuilder();
+    private static Formatter sFormatter = new Formatter(sFormatBuilder, Locale
+                                                       .getDefault());
+    private static final Object[] sTimeArgs = new Object[5];
+
     private final String FREQ_LIST_FILE_NAME = "/freq_list_comma_separated.txt";
+    private static final String BAND_SWEEP_START_DELAY_TIMEOUT = "com.caf.fmradio.SWEEP_START_DELAY_EXP";
+    private static final String BAND_SWEEP_DWELL_DELAY_TIMEOUT = "com.caf.fmradio.SWEEP_DWELL_DELAY_EXP";
+
+    private BroadcastReceiver mBandSweepDelayExprdListener = null;
+    private BroadcastReceiver mBandSweepDwellExprdListener = null;
+
+    private WakeLock mWakeLock;
+
+    private GetNextFreqInterface mNextFreqInterface;
+    private CommaSeparatedFreqFileReader mFreqFileReader;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -300,28 +335,50 @@
         if(bandSweepSettingButton != null) {
            bandSweepSettingButton.setOnClickListener(mClicktBandSweepSettingListener);
         }
+
+        PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.getClass().getName());
+        mWakeLock.setReferenceCounted(false);
+
+        registerBandSweepDelayExprdListener();
+        registerBandSweepDwellExprdListener();
     }
 
+    @Override
+    public void onStart() {
+       super.onStart();
+       if(isRecording()) {
+          Log.d(LOGTAG, "onStart");
+          initiateRecordThread();
+       }
+    }
+
+    @Override
+    public void onStop() {
+       super.onStop();
+       if(isRecording()) {
+          try {
+               if(null != mRecordUpdateHandlerThread) {
+                  mRecordUpdateHandlerThread.interrupt();
+               }
+          }catch (NullPointerException e) {
+               e.printStackTrace();
+          }
+       }
+    }
+
+    @Override
     public void onDestroy() {
+
+        stopCurTest();
+
+        unRegisterBroadcastReceiver(mBandSweepDelayExprdListener);
+        unRegisterBroadcastReceiver(mBandSweepDwellExprdListener);
+
         if(null != mFileCursor ) {
             try {
                 mFileCursor.close();
             } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
-        /*Stop the thread by interrupting it*/
-        if(mMultiUpdateThread != null) {
-           mMultiUpdateThread.interrupt();
-           mMultiUpdateThread = null;
-        }
-        /*Stop the search/scan if there is an ongoing*/
-        if(SEARCH_TEST == mTestSelected)
-        {
-           Log.d(LOGTAG, "Stop Search\n");
-           try {
-                 mService.cancelSearch();
-           } catch (RemoteException e) {
                  e.printStackTrace();
            }
         }
@@ -331,6 +388,7 @@
         mReceiver = null;
         mService = null;
         removeDialog(DIALOG_BAND_SWEEP_SETTING);
+        mWakeLock.release();
         super.onDestroy();
     }
 
@@ -345,7 +403,6 @@
               runCurrentTest();
            }else {
               mTestRunning = false;
-              /*Set it back to ready to Run*/
               SetButtonState(true);
               /*Stop the thread by interrupting it*/
               if(mMultiUpdateThread != null) {
@@ -361,6 +418,8 @@
                  }
               }
               if(mTestSelected == SWEEP_TEST) {
+                 stopBandSweep();
+                 sendStatusDoneMsg();
                  enableBandSweepSetting();
               }
            }
@@ -1675,6 +1734,7 @@
        }
        mBand.lFreq = lFreq;
        mBand.hFreq = hFreq;
+       mBand.cur_freq = lFreq;
        if(Spacing == 0) {
           mBand.Spacing = 200; // 200KHz
        }else if(Spacing == 1) {
@@ -1683,52 +1743,26 @@
           mBand.Spacing = 50;
        }
 
-       if(mMultiUpdateThread == null) {
-          if(prevSweepMthd == 0) {
-             mMultiUpdateThread = new Thread(null, getManualSweepResults,
-                                           "MultiResultsThread");
-          }else {
-             mMultiUpdateThread = new Thread(null, getFileSweepResults,
-                                           "MultiResultsThread");
-          }
-       }
-       /* Launch he dummy thread to simulate the transfer progress */
-       Log.d(LOGTAG, "Thread State: " + mMultiUpdateThread.getState());
-       if((mMultiUpdateThread.getState() == Thread.State.TERMINATED)) {
-          if(prevSweepMthd == 0) {
-             mMultiUpdateThread = new Thread(null, getManualSweepResults,
-                                                  "MultiResultsThread");
-          }else {
-             mMultiUpdateThread = new Thread(null, getFileSweepResults,
-                                           "MultiResultsThread");
-          }
-       }
-       /* If the thread state is "new" then the thread has not yet started */
-       if(mMultiUpdateThread.getState() == Thread.State.NEW) {
-          mMultiUpdateThread.start();
-       }
+       setAlarm(prevDelayTime * 1000, BAND_SWEEP_START_DELAY_TIMEOUT);
     }
 
     /* Thread processing */
     private Runnable getManualSweepResults = new Runnable() {
        public void run() {
-            try {
-                Thread.sleep(prevDelayTime * 1000);
-            }catch(InterruptedException e) {
-            }
-            for (int i = mBand.lFreq; (i <= mBand.hFreq) &&
-                                     (mService != null); i += mBand.Spacing) {
-                 if(!tuneAndUpdateSweepResult(i)) {
-                    break;
-                 }
-                 try {
-                     Thread.sleep(prevDwellTime * 1000);
-                 }catch (InterruptedException e) {
-                     /*Stop the thrad*/
-                     break;
-                 }
-            }
-            sendStatusDoneMsg();
+           mWakeLock.acquire(10 * 1000);
+           if(mBand.cur_freq <= mBand.hFreq) {
+              if(!tuneAndUpdateSweepResult(mBand.cur_freq)) {
+                 sendStatusDoneMsg();
+              }
+              mBand.cur_freq += mBand.Spacing;
+              if(mBand.cur_freq > mBand.hFreq) {
+                 sendStatusDoneMsg();
+              }else {
+                 setAlarm(prevDwellTime * 1000, BAND_SWEEP_DWELL_DELAY_TIMEOUT);
+              }
+           }else {
+              sendStatusDoneMsg();
+           }
        }
     };
 
@@ -1750,46 +1784,29 @@
 
     private Runnable getFileSweepResults = new Runnable() {
        public void run() {
-          boolean status = true;
-          try {
-               BufferedReader reader = new BufferedReader
-                               (new FileReader(getFilesDir()
-                                                + FREQ_LIST_FILE_NAME));
-               String curLine = null;
-               try {
-                    Thread.sleep(prevDelayTime * 1000);
-               }catch(InterruptedException e) {
+         boolean status = true;
+         int freq;
+
+         mWakeLock.acquire(10 * 1000);
+         freq = mNextFreqInterface.getNextFreq();
+
+         for(; (status = (!mNextFreqInterface.errorOccured()) & (!Thread.currentThread().isInterrupted()));
+                  freq = mNextFreqInterface.getNextFreq()) {
+            if(validFreq(freq)) {
+               if(!tuneAndUpdateSweepResult(freq)) {
+                  status = false;
+                  break;
+               }else {
+                  setAlarm(prevDwellTime * 1000, BAND_SWEEP_DWELL_DELAY_TIMEOUT);
+                  break;
                }
-               while((reader != null) && (curLine = reader.readLine()) != null) {
-                     String[] freq_list = curLine.split(",");
-                     for(int i = 0; (freq_list != null ) &&
-                                      (i < freq_list.length); i++) {
-                         int freq =
-                             (int)(Double.parseDouble(freq_list[i]) * 1000);
-                         if(validFreq(freq)) {
-                            if(!tuneAndUpdateSweepResult(freq)) {
-                               status = false;
-                               break;
-                            }else {
-                               try {
-                                   Thread.sleep(prevDwellTime * 1000);
-                               }catch (InterruptedException e) {
-                                   /*Stop the thrad*/
-                                   status = false;
-                                   break;
-                               }
-                            }
-                         }
-                     }
-                     if(!status) {
-                        break;
-                     }
-               }
-               reader.close();
-          }catch(IOException e) {
-               e.printStackTrace();
-          }
-          sendStatusDoneMsg();
+            }
+         }
+         if(!status) {
+            sendStatusDoneMsg();
+            mNextFreqInterface.Stop();
+            mNextFreqInterface = null;
+         }
        }
     };
 
@@ -1917,6 +1934,17 @@
                case STATUS_DONE:
                     SetButtonState(true);
                     break;
+               case RECORDTIMER_EXPIRED:
+                    Log.d(LOGTAG, "mUIUpdateHandlerHandler - RECORDTIMER_EXPIRED");
+                    if(!isRecording()) {
+                       Log.d(LOGTAG, "Stop Recording");
+                       stopRecording();
+                    }
+                   break;
+               case RECORDTIMER_UPDATE:
+                   Log.d(LOGTAG, "mUIUpdateHandlerHandler - RECORDTIMER_UPDATE");
+                   updateExpiredRecordTime();
+                   break;
                }
             }
     };
@@ -1995,6 +2023,9 @@
                 {
                    e.printStackTrace();
                 }
+                if(isRecording()) {
+                   initiateRecordThread();
+                }
                 return;
              } else
              {
@@ -2012,17 +2043,19 @@
           public void onEnabled()
           {
              Log.d(LOGTAG, "mServiceCallbacks.onEnabled :");
+             invalidateOptionsMenu();
           }
 
           public void onDisabled()
           {
              Log.d(LOGTAG, "mServiceCallbacks.onDisabled :");
-             stopCurTest();
+             stopAllOperations();
           }
 
           public void onRadioReset()
           {
              Log.d(LOGTAG, "mServiceCallbacks.onRadioReset :");
+             stopAllOperations();
           }
 
           public void onTuneStatusChanged()
@@ -2087,6 +2120,7 @@
           public void onRecordingStopped()
           {
              Log.d(LOGTAG, "mServiceCallbacks.onDisabled :");
+             stopRecording();
           }
           public void onFinishActivity()
           {
@@ -2095,6 +2129,10 @@
           public void onRecordingStarted()
           {
              Log.d(LOGTAG, "mServiceCallbacks.onRecordingStarted:");
+             int durationInMins = FmSharedPreferences.getRecordDuration();
+             Log.e(LOGTAG, " Fected duration: " + durationInMins);
+             initiateRecordDurationTimer(durationInMins);
+             invalidateOptionsMenu();
           }
       };
       /* Radio Vars */
@@ -2128,6 +2166,9 @@
              case CUR_FREQ_TEST:
                   break;
              case SWEEP_TEST:
+                  stopBandSweep();
+                  sendStatusDoneMsg();
+                  break;
              case CUR_MULTI_TEST:
                   if (mMultiUpdateThread != null)
                       mMultiUpdateThread.interrupt();
@@ -2235,4 +2276,286 @@
         }
     }
 
- }
+    private void registerBandSweepDelayExprdListener() {
+        if(mBandSweepDelayExprdListener == null) {
+           mBandSweepDelayExprdListener = new BroadcastReceiver() {
+              @Override
+               public void onReceive(Context context, Intent intent) {
+                   Log.d(LOGTAG, "Received Band sweep delay expired");
+                   mWakeLock.acquire(5 * 1000);
+                   StartBandSweep();
+               }
+           };
+           IntentFilter intentFilter = new IntentFilter(BAND_SWEEP_START_DELAY_TIMEOUT);
+           registerReceiver(mBandSweepDelayExprdListener, intentFilter);
+        }
+    }
+
+    private void registerBandSweepDwellExprdListener() {
+        if(mBandSweepDwellExprdListener == null) {
+           mBandSweepDwellExprdListener = new BroadcastReceiver() {
+              @Override
+               public void onReceive(Context context, Intent intent) {
+                   Log.d(LOGTAG, "received Band sweep Dwell expired");
+                   mWakeLock.acquire(5 * 1000);
+                   ResumeBandSweep();
+               }
+           };
+           IntentFilter intentFilter = new IntentFilter(BAND_SWEEP_DWELL_DELAY_TIMEOUT);
+           registerReceiver(mBandSweepDwellExprdListener, intentFilter);
+        }
+    }
+
+    private void unRegisterBroadcastReceiver(BroadcastReceiver receiver) {
+        if(receiver != null) {
+           unregisterReceiver(receiver);
+           receiver = null;
+        }
+    }
+
+    private void setAlarm(long duration, String action) {
+        Intent i = new Intent(action);
+        AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
+        PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
+        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + duration, pi);
+    }
+
+    private void cancelAlarm(String action) {
+        Intent i = new Intent(action);
+        AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
+        PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
+        am.cancel(pi);
+    }
+
+    private void StartBandSweep() {
+       if(mMultiUpdateThread == null ||
+            (mMultiUpdateThread.getState() == Thread.State.TERMINATED)) {
+          if(prevSweepMthd == 0) {
+             mMultiUpdateThread = new Thread(null, getManualSweepResults,
+                                           "MultiResultsThread");
+          }else {
+             mNextFreqInterface = new CommaSeparatedFreqFileReader(getFilesDir() + FREQ_LIST_FILE_NAME);
+             mMultiUpdateThread = new Thread(null, getFileSweepResults,
+                                           "MultiResultsThread");
+          }
+       }
+
+       /* If the thread state is "new" then the thread has not yet started */
+       if(mMultiUpdateThread.getState() == Thread.State.NEW) {
+          mMultiUpdateThread.start();
+       }
+    }
+
+    private void ResumeBandSweep() {
+       if(mMultiUpdateThread == null ||
+            (mMultiUpdateThread.getState() == Thread.State.TERMINATED)) {
+          if(prevSweepMthd == 0) {
+             mMultiUpdateThread = new Thread(null, getManualSweepResults,
+                                           "MultiResultsThread");
+          }else {
+             mMultiUpdateThread = new Thread(null, getFileSweepResults,
+                                           "MultiResultsThread");
+          }
+       }
+
+       /* If the thread state is "new" then the thread has not yet started */
+       if(mMultiUpdateThread.getState() == Thread.State.NEW) {
+          mMultiUpdateThread.start();
+       }
+    }
+
+    private void stopBandSweep() {
+       cancelAlarm(BAND_SWEEP_START_DELAY_TIMEOUT);
+       cancelAlarm(BAND_SWEEP_DWELL_DELAY_TIMEOUT);
+       if(mMultiUpdateThread != null) {
+          mMultiUpdateThread.interrupt();
+       }
+       if(mNextFreqInterface != null) {
+          mNextFreqInterface.Stop();
+          mNextFreqInterface = null;
+       }
+    }
+
+    public boolean isRecording() {
+       if(mService == null)
+          return false;
+       try {
+            return mService.isFmRecordingOn();
+       }catch(RemoteException e) {
+            return false;
+       }
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.menu_rf_stats, menu);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        MenuItem item;
+
+        item = menu.findItem(R.id.menu_recording);
+        if(item != null && !isRecording()) {
+           item.setTitle(R.string.menu_record_start);
+           item.setEnabled(isFmOn());
+        }else if(item != null) {
+           item.setTitle(R.string.menu_record_stop);
+           setRecordDurationDisplay(menu, R.id.menu_record_duration);
+        }
+        return true;
+    }
+
+    private void setRecordDurationDisplay(Menu menu, int id) {
+       MenuItem item;
+       long timeNow;
+       long seconds;
+
+       if(menu == null)
+          return;
+       item = menu.findItem(id);
+       if(item != null) {
+          timeNow = SystemClock.elapsedRealtime();
+          seconds = (timeNow - getRecordingStartTime()) / 1000;
+          item.setTitle(makeTimeString(seconds));
+       }
+    }
+
+    private void startRecording() {
+      if(isFmOn()) {
+         try {
+              mService.startRecording();
+         }catch(RemoteException e) {
+              e.printStackTrace();
+         }
+      }
+    }
+
+    private void stopRecording() {
+       if(null != mRecordUpdateHandlerThread) {
+          mRecordUpdateHandlerThread.interrupt();
+       }
+       if(mService != null) {
+          try {
+               mService.stopRecording();
+           }catch (RemoteException e) {
+               e.printStackTrace();
+           }
+        }
+        invalidateOptionsMenu();
+    }
+
+    private long getRecordingStartTime() {
+       if(mService == null)
+          return 0;
+       try {
+            return mService.getRecordingStartTime();
+       }catch(RemoteException e) {
+            return 0;
+       }
+    }
+
+    private void initiateRecordDurationTimer(long mins ) {
+       Log.d(LOGTAG, "Stop Recording in mins : " + mins);
+       initiateRecordThread();
+    }
+
+    private void initiateRecordThread() {
+      if(mRecordUpdateHandlerThread == null) {
+         mRecordUpdateHandlerThread = new Thread(null, doRecordProcessing,
+                                                "RecordUpdateThread");
+      }
+      /* Launch the dummy thread to simulate the transfer progress */
+      Log.d(LOGTAG, "Thread State: " + mRecordUpdateHandlerThread.getState());
+      if(mRecordUpdateHandlerThread.getState() == Thread.State.TERMINATED) {
+         mRecordUpdateHandlerThread = new Thread(null, doRecordProcessing,
+                                                "RecordUpdateThread");
+      }
+      /* If the thread state is "new" then the thread has not yet started */
+      if(mRecordUpdateHandlerThread.getState() == Thread.State.NEW) {
+         mRecordUpdateHandlerThread.start();
+      }
+   }
+
+   /* Recorder Thread processing */
+   private Runnable doRecordProcessing = new Runnable() {
+      public void run() {
+         while(isRecording() &&
+                 (!Thread.currentThread().isInterrupted())) {
+               try {
+                    Thread.sleep(500);
+                    Message statusUpdate = new Message();
+                    statusUpdate.what = RECORDTIMER_UPDATE;
+                    mUIUpdateHandlerHandler.sendMessage(statusUpdate);
+               }catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+               }
+               if(!isRecording()) {
+                  Message finished = new Message();
+                  finished.what = RECORDTIMER_EXPIRED;
+                  mUIUpdateHandlerHandler.sendMessage(finished);
+               }
+         }
+      }
+   };
+
+   private void updateExpiredRecordTime() {
+      int vis = View.VISIBLE;
+      if(isRecording()) {
+         invalidateOptionsMenu();
+      }
+   }
+
+   private String makeTimeString(long secs) {
+      String durationformat = getString(R.string.durationformat);
+
+      /** Provide multiple arguments so the format can be changed easily by
+       *  modifying the xml.
+       **/
+      sFormatBuilder.setLength(0);
+
+      final Object[] timeArgs = sTimeArgs;
+      timeArgs[0] = secs / 3600;
+      timeArgs[1] = secs / 60;
+      timeArgs[2] = (secs / 60) % 60;
+      timeArgs[3] = secs;
+      timeArgs[4] = secs % 60;
+
+      return sFormatter.format(durationformat, timeArgs).toString();
+   }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch(item.getItemId())
+        {
+          case R.id.menu_recording:
+               if(isRecording()) {
+                  stopRecording();
+               }else {
+                  startRecording();
+               }
+               break;
+        }
+        return true;
+    }
+
+    private boolean isFmOn() {
+       boolean status = false;
+
+       if(mService != null) {
+          try {
+               status = mService.isFmOn();
+          }catch(RemoteException e) {
+          }
+       }
+       return status;
+    }
+
+    private void stopAllOperations() {
+       stopCurTest();
+       stopRecording();
+    }
+}
diff --git a/fmapp2/src/com/caf/fmradio/GetNextFreqInterface.java b/fmapp2/src/com/caf/fmradio/GetNextFreqInterface.java
new file mode 100644
index 0000000..2a5ee53
--- /dev/null
+++ b/fmapp2/src/com/caf/fmradio/GetNextFreqInterface.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *        * Redistributions of source code must retain the above copyright
+ *            notice, this list of conditions and the following disclaimer.
+ *        * Redistributions in binary form must reproduce the above copyright
+ *            notice, this list of conditions and the following disclaimer in the
+ *            documentation and/or other materials provided with the distribution.
+ *        * Neither the name of The Linux Foundation nor
+ *            the names of its contributors may be used to endorse or promote
+ *            products derived from this software without specific prior written
+ *            permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT ARE DISCLAIMED.    IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.caf.fmradio;
+public interface GetNextFreqInterface {
+   public int getNextFreq();
+   public void Stop();
+   public boolean errorOccured();
+}
diff --git a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
index c2dc7fb..fe54124 100644
--- a/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
+++ b/fmapp2/src/com/caf/fmradio/IFMRadioService.aidl
@@ -70,5 +70,6 @@
     int getGoodChRmssiTh();
     int getAfJmpRmssiSamplesCnt();
     boolean setRxRepeatCount(int count);
+    long getRecordingStartTime();
 }