• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.fmradio;
18 
19 import android.content.Context;
20 import android.content.SharedPreferences;
21 import android.content.res.Resources;
22 import android.graphics.Bitmap;
23 import android.os.Environment;
24 import android.os.StatFs;
25 import android.os.storage.StorageManager;
26 import android.preference.PreferenceManager;
27 import android.util.Log;
28 import android.view.View.MeasureSpec;
29 import android.widget.LinearLayout;
30 import android.widget.TextView;
31 
32 import java.text.DecimalFormat;
33 import java.util.Locale;
34 
35 /**
36  * This class provider interface to compute station and frequency, get project
37  * string
38  */
39 public class FmUtils {
40     private static final String TAG = "FmUtils";
41 
42     // FM station variables
43     public static final int DEFAULT_STATION = 1000;
44     public static final float DEFAULT_STATION_FLOAT = computeFrequency(DEFAULT_STATION);
45     // maximum station frequency
46     private static final int HIGHEST_STATION = 1080;
47     // minimum station frequency
48     private static final int LOWEST_STATION = 875;
49     // station step
50     private static final int STEP = 1;
51     // convert rate
52     private static final int CONVERT_RATE = 10;
53 
54     // minimum storage space for record (512KB).
55     // Need to check before starting recording and during recording to avoid
56     // recording keeps going but there is no free space in sdcard.
57     public static final long LOW_SPACE_THRESHOLD = 512 * 1024;
58     // Different city may have different RDS information.
59     // We define 100 miles (160934.4m) to distinguish the cities.
60     public static final double LOCATION_DISTANCE_EXCEED = 160934.4;
61     private static final String FM_LOCATION_LATITUDE = "fm_location_latitude";
62     private static final String FM_LOCATION_LONGITUDE = "fm_location_longitude";
63     private static final String FM_IS_FIRST_TIME_PLAY = "fm_is_first_time_play";
64     private static final String FM_IS_SPEAKER_MODE = "fm_is_speaker_mode";
65     private static final String FM_IS_FIRST_ENTER_STATION_LIST = "fm_is_first_enter_station_list";
66     // StorageManager For FM record
67     private static StorageManager sStorageManager = null;
68 
69     /**
70      * Whether the frequency is valid.
71      *
72      * @param station The FM station
73      *
74      * @return true if the frequency is in the valid scale, otherwise return
75      *         false
76      */
isValidStation(int station)77     public static boolean isValidStation(int station) {
78         boolean isValid = (station >= LOWEST_STATION && station <= HIGHEST_STATION);
79         return isValid;
80     }
81 
82     /**
83      * Compute increase station frequency
84      *
85      * @param station The station frequency
86      *
87      * @return station The frequency after increased
88      */
computeIncreaseStation(int station)89     public static int computeIncreaseStation(int station) {
90         int result = station + STEP;
91         if (result > HIGHEST_STATION) {
92             result = LOWEST_STATION;
93         }
94         return result;
95     }
96 
97     /**
98      * Compute decrease station frequency
99      *
100      * @param station The station frequency
101      *
102      * @return station The frequency after decreased
103      */
computeDecreaseStation(int station)104     public static int computeDecreaseStation(int station) {
105         int result = station - STEP;
106         if (result < LOWEST_STATION) {
107             result = HIGHEST_STATION;
108         }
109         return result;
110     }
111 
112     /**
113      * Compute station value with given frequency
114      *
115      * @param frequency The station frequency
116      *
117      * @return station The result value
118      */
computeStation(float frequency)119     public static int computeStation(float frequency) {
120         return (int) (frequency * CONVERT_RATE);
121     }
122 
123     /**
124      * Compute frequency value with given station
125      *
126      * @param station The station value
127      *
128      * @return station The frequency
129      */
computeFrequency(int station)130     public static float computeFrequency(int station) {
131         return (float) station / CONVERT_RATE;
132     }
133 
134     /**
135      * According station to get frequency string
136      *
137      * @param station for 100KZ, range 875-1080
138      *
139      * @return string like 87.5
140      */
formatStation(int station)141     public static String formatStation(int station) {
142         float frequency = (float) station / CONVERT_RATE;
143         DecimalFormat decimalFormat = new DecimalFormat("0.0");
144         return decimalFormat.format(frequency);
145     }
146 
147     /**
148      * Get the phone storage path
149      *
150      * @return The phone storage path
151      */
getDefaultStoragePath()152     public static String getDefaultStoragePath() {
153         return Environment.getExternalStorageDirectory().getPath();
154     }
155 
156     /**
157      * Get the default storage state
158      *
159      * @return The default storage state
160      */
getDefaultStorageState(Context context)161     public static String getDefaultStorageState(Context context) {
162         ensureStorageManager(context);
163         String state = sStorageManager.getVolumeState(getDefaultStoragePath());
164         return state;
165     }
166 
ensureStorageManager(Context context)167     private static void ensureStorageManager(Context context) {
168         if (sStorageManager == null) {
169             sStorageManager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
170         }
171     }
172 
173     /**
174      * Get the FM play list path
175      *
176      * @param context The context
177      *
178      * @return The FM play list path
179      */
getPlaylistPath(Context context)180     public static String getPlaylistPath(Context context) {
181         ensureStorageManager(context);
182         String[] externalStoragePaths = sStorageManager.getVolumePaths();
183         String path = externalStoragePaths[0] + "/Playlists/";
184         return path;
185     }
186 
187     /**
188      * Check if has enough space for record
189      *
190      * @param recordingSdcard The recording sdcard path
191      *
192      * @return true if has enough space for record
193      */
hasEnoughSpace(String recordingSdcard)194     public static boolean hasEnoughSpace(String recordingSdcard) {
195         boolean ret = false;
196         try {
197             StatFs fs = new StatFs(recordingSdcard);
198             long blocks = fs.getAvailableBlocks();
199             long blockSize = fs.getBlockSize();
200             long spaceLeft = blocks * blockSize;
201             ret = spaceLeft > LOW_SPACE_THRESHOLD ? true : false;
202         } catch (IllegalArgumentException e) {
203             Log.e(TAG, "hasEnoughSpace, sdcard may be unmounted:" + recordingSdcard);
204         }
205         return ret;
206     }
207 
208     /**
209      * Get the latest searched location
210      * @return the list of latitude and longitude
211      */
getLastSearchedLocation(Context context)212     public static double[] getLastSearchedLocation(Context context) {
213         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
214 
215         String strLatitude = prefs.getString(FM_LOCATION_LATITUDE, "0.0");
216         String strLongitude = prefs.getString(FM_LOCATION_LONGITUDE, "0.0");
217         double latitude = Double.valueOf(strLatitude);
218         double longitude = Double.valueOf(strLongitude);
219         return new double[] { latitude, longitude };
220     }
221 
222     /**
223      * Set the last searched location
224      */
setLastSearchedLocation(Context context, double latitude, double longitude)225     public static void setLastSearchedLocation(Context context, double latitude, double longitude) {
226         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
227         SharedPreferences.Editor editor = prefs.edit();
228         String strLatitude = Double.valueOf(latitude).toString();
229         String strLongitude = Double.valueOf(longitude).toString();
230         editor.putString(FM_LOCATION_LATITUDE, strLatitude);
231         editor.putString(FM_LOCATION_LONGITUDE, strLongitude);
232         editor.commit();
233     }
234 
235     /**
236      * check it is the first time to use Fm
237      */
isFirstTimePlayFm(Context context)238     public static boolean isFirstTimePlayFm(Context context) {
239         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
240         boolean isFirstTime = prefs.getBoolean(FM_IS_FIRST_TIME_PLAY, true);
241         return isFirstTime;
242     }
243 
244     /**
245      * Called when first time play FM.
246      * @param context The context
247      */
setIsFirstTimePlayFm(Context context)248     public static void setIsFirstTimePlayFm(Context context) {
249         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
250         SharedPreferences.Editor editor = prefs.edit();
251         editor.putBoolean(FM_IS_FIRST_TIME_PLAY, false);
252         editor.commit();
253     }
254 
255     /**
256      * check it is the first time enter into station list page
257      */
isFirstEnterStationList(Context context)258     public static boolean isFirstEnterStationList(Context context) {
259         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
260         boolean isFirstEnter = prefs.getBoolean(FM_IS_FIRST_ENTER_STATION_LIST, true);
261         if (isFirstEnter) {
262             SharedPreferences.Editor editor = prefs.edit();
263             editor.putBoolean(FM_IS_FIRST_ENTER_STATION_LIST, false);
264             editor.commit();
265         }
266         return isFirstEnter;
267     }
268 
269     /**
270      * Create the notification large icon bitmap from layout
271      * @param c The context
272      * @param text The frequency text
273      * @return The large icon bitmap with frequency text
274      */
createNotificationLargeIcon(Context c, String text)275     public static Bitmap createNotificationLargeIcon(Context c, String text) {
276         Resources res = c.getResources();
277         int width = (int) res.getDimension(android.R.dimen.notification_large_icon_width);
278         int height = (int) res.getDimension(android.R.dimen.notification_large_icon_height);
279         LinearLayout iconLayout = new LinearLayout(c);
280         iconLayout.setOrientation(LinearLayout.VERTICAL);
281         iconLayout.setBackgroundColor(c.getResources().getColor(R.color.theme_primary_color));
282         iconLayout.setDrawingCacheEnabled(true);
283         iconLayout.layout(0, 0, width, height);
284         TextView iconText = new TextView(c);
285         iconText.setTextSize(24.0f);
286         iconText.setTextColor(res.getColor(R.color.theme_title_color));
287         iconText.setText(text);
288         iconText.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
289                 MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
290         int left = (int) ((width - iconText.getMeasuredWidth()) * 0.5);
291         int top = (int) ((height - iconText.getMeasuredHeight()) * 0.5);
292         iconText.layout(left, top, iconText.getMeasuredWidth() + left,
293                 iconText.getMeasuredHeight() + top);
294         iconLayout.addView(iconText);
295         iconLayout.layout(0, 0, width, height);
296 
297         iconLayout.buildDrawingCache();
298         Bitmap largeIcon = Bitmap.createBitmap(iconLayout.getDrawingCache());
299         iconLayout.destroyDrawingCache();
300         return largeIcon;
301     }
302 
303     /**
304      * Get whether speaker mode is in use when audio focus lost.
305      * @param context the Context
306      * @return true for speaker mode, false for non speaker mode
307      */
getIsSpeakerModeOnFocusLost(Context context)308     public static boolean getIsSpeakerModeOnFocusLost(Context context) {
309         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
310 
311         return prefs.getBoolean(FM_IS_SPEAKER_MODE, false);
312     }
313 
314     /**
315      * Set whether speaker mode is in use.
316      * @param context the Context
317      * @param isSpeaker speaker state
318      */
setIsSpeakerModeOnFocusLost(Context context, boolean isSpeaker)319     public static void setIsSpeakerModeOnFocusLost(Context context, boolean isSpeaker) {
320         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
321         SharedPreferences.Editor editor = prefs.edit();
322         editor.putBoolean(FM_IS_SPEAKER_MODE, isSpeaker);
323         editor.commit();
324     }
325 }
326