• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2007 Google Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations
14  * under the License.
15  */
16 
17 package com.android.settings;
18 
19 import android.app.ActivityManager;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.PackageManager.NameNotFoundException;
25 import android.content.pm.ResolveInfo;
26 import android.content.res.Resources;
27 import android.content.res.Resources.NotFoundException;
28 import android.graphics.drawable.Drawable;
29 import android.net.ConnectivityManager;
30 import android.net.LinkProperties;
31 import android.os.BatteryManager;
32 import android.os.Bundle;
33 import android.os.SystemProperties;
34 import android.preference.Preference;
35 import android.preference.PreferenceActivity.Header;
36 import android.preference.PreferenceFrameLayout;
37 import android.preference.PreferenceGroup;
38 import android.telephony.TelephonyManager;
39 import android.text.TextUtils;
40 import android.view.View;
41 import android.view.ViewGroup;
42 import android.widget.ListView;
43 import android.widget.TabWidget;
44 
45 import java.net.InetAddress;
46 import java.util.Iterator;
47 import java.util.List;
48 import java.util.Locale;
49 
50 public class Utils {
51 
52     /**
53      * Set the preference's title to the matching activity's label.
54      */
55     public static final int UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY = 1;
56 
57     /**
58      * Name of the meta-data item that should be set in the AndroidManifest.xml
59      * to specify the icon that should be displayed for the preference.
60      */
61     private static final String META_DATA_PREFERENCE_ICON = "com.android.settings.icon";
62 
63     /**
64      * Name of the meta-data item that should be set in the AndroidManifest.xml
65      * to specify the title that should be displayed for the preference.
66      */
67     private static final String META_DATA_PREFERENCE_TITLE = "com.android.settings.title";
68 
69     /**
70      * Name of the meta-data item that should be set in the AndroidManifest.xml
71      * to specify the summary text that should be displayed for the preference.
72      */
73     private static final String META_DATA_PREFERENCE_SUMMARY = "com.android.settings.summary";
74 
75     /**
76      * Finds a matching activity for a preference's intent. If a matching
77      * activity is not found, it will remove the preference.
78      *
79      * @param context The context.
80      * @param parentPreferenceGroup The preference group that contains the
81      *            preference whose intent is being resolved.
82      * @param preferenceKey The key of the preference whose intent is being
83      *            resolved.
84      * @param flags 0 or one or more of
85      *            {@link #UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY}
86      *            .
87      * @return Whether an activity was found. If false, the preference was
88      *         removed.
89      */
updatePreferenceToSpecificActivityOrRemove(Context context, PreferenceGroup parentPreferenceGroup, String preferenceKey, int flags)90     public static boolean updatePreferenceToSpecificActivityOrRemove(Context context,
91             PreferenceGroup parentPreferenceGroup, String preferenceKey, int flags) {
92 
93         Preference preference = parentPreferenceGroup.findPreference(preferenceKey);
94         if (preference == null) {
95             return false;
96         }
97 
98         Intent intent = preference.getIntent();
99         if (intent != null) {
100             // Find the activity that is in the system image
101             PackageManager pm = context.getPackageManager();
102             List<ResolveInfo> list = pm.queryIntentActivities(intent, 0);
103             int listSize = list.size();
104             for (int i = 0; i < listSize; i++) {
105                 ResolveInfo resolveInfo = list.get(i);
106                 if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
107                         != 0) {
108 
109                     // Replace the intent with this specific activity
110                     preference.setIntent(new Intent().setClassName(
111                             resolveInfo.activityInfo.packageName,
112                             resolveInfo.activityInfo.name));
113 
114                     if ((flags & UPDATE_PREFERENCE_FLAG_SET_TITLE_TO_MATCHING_ACTIVITY) != 0) {
115                         // Set the preference title to the activity's label
116                         preference.setTitle(resolveInfo.loadLabel(pm));
117                     }
118 
119                     return true;
120                 }
121             }
122         }
123 
124         // Did not find a matching activity, so remove the preference
125         parentPreferenceGroup.removePreference(preference);
126 
127         return true;
128     }
129 
130     /**
131      * Finds a matching activity for a preference's intent. If a matching
132      * activity is not found, it will remove the preference. The icon, title and
133      * summary of the preference will also be updated with the values retrieved
134      * from the activity's meta-data elements. If no meta-data elements are
135      * specified then the preference title will be set to match the label of the
136      * activity, an icon and summary text will not be displayed.
137      *
138      * @param context The context.
139      * @param parentPreferenceGroup The preference group that contains the
140      *            preference whose intent is being resolved.
141      * @param preferenceKey The key of the preference whose intent is being
142      *            resolved.
143      *
144      * @return Whether an activity was found. If false, the preference was
145      *         removed.
146      *
147      * @see {@link #META_DATA_PREFERENCE_ICON}
148      *      {@link #META_DATA_PREFERENCE_TITLE}
149      *      {@link #META_DATA_PREFERENCE_SUMMARY}
150      */
updatePreferenceToSpecificActivityFromMetaDataOrRemove(Context context, PreferenceGroup parentPreferenceGroup, String preferenceKey)151     public static boolean updatePreferenceToSpecificActivityFromMetaDataOrRemove(Context context,
152             PreferenceGroup parentPreferenceGroup, String preferenceKey) {
153 
154         IconPreferenceScreen preference = (IconPreferenceScreen)parentPreferenceGroup
155                 .findPreference(preferenceKey);
156         if (preference == null) {
157             return false;
158         }
159 
160         Intent intent = preference.getIntent();
161         if (intent != null) {
162             // Find the activity that is in the system image
163             PackageManager pm = context.getPackageManager();
164             List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
165             int listSize = list.size();
166             for (int i = 0; i < listSize; i++) {
167                 ResolveInfo resolveInfo = list.get(i);
168                 if ((resolveInfo.activityInfo.applicationInfo.flags
169                         & ApplicationInfo.FLAG_SYSTEM) != 0) {
170                     Drawable icon = null;
171                     String title = null;
172                     String summary = null;
173 
174                     // Get the activity's meta-data
175                     try {
176                         Resources res = pm
177                                 .getResourcesForApplication(resolveInfo.activityInfo.packageName);
178                         Bundle metaData = resolveInfo.activityInfo.metaData;
179 
180                         if (res != null && metaData != null) {
181                             icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
182                             title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
183                             summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
184                         }
185                     } catch (NameNotFoundException e) {
186                         // Ignore
187                     } catch (NotFoundException e) {
188                         // Ignore
189                     }
190 
191                     // Set the preference title to the activity's label if no
192                     // meta-data is found
193                     if (TextUtils.isEmpty(title)) {
194                         title = resolveInfo.loadLabel(pm).toString();
195                     }
196 
197                     // Set icon, title and summary for the preference
198                     preference.setIcon(icon);
199                     preference.setTitle(title);
200                     preference.setSummary(summary);
201 
202                     // Replace the intent with this specific activity
203                     preference.setIntent(new Intent().setClassName(
204                             resolveInfo.activityInfo.packageName,
205                             resolveInfo.activityInfo.name));
206 
207                    return true;
208                 }
209             }
210         }
211 
212         // Did not find a matching activity, so remove the preference
213         parentPreferenceGroup.removePreference(preference);
214 
215         return false;
216     }
217 
updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context, List<Header> target, Header header)218     public static boolean updateHeaderToSpecificActivityFromMetaDataOrRemove(Context context,
219             List<Header> target, Header header) {
220 
221         Intent intent = header.intent;
222         if (intent != null) {
223             // Find the activity that is in the system image
224             PackageManager pm = context.getPackageManager();
225             List<ResolveInfo> list = pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
226             int listSize = list.size();
227             for (int i = 0; i < listSize; i++) {
228                 ResolveInfo resolveInfo = list.get(i);
229                 if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
230                         != 0) {
231                     Drawable icon = null;
232                     String title = null;
233                     String summary = null;
234 
235                     // Get the activity's meta-data
236                     try {
237                         Resources res = pm.getResourcesForApplication(
238                                 resolveInfo.activityInfo.packageName);
239                         Bundle metaData = resolveInfo.activityInfo.metaData;
240 
241                         if (res != null && metaData != null) {
242                             icon = res.getDrawable(metaData.getInt(META_DATA_PREFERENCE_ICON));
243                             title = res.getString(metaData.getInt(META_DATA_PREFERENCE_TITLE));
244                             summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
245                         }
246                     } catch (NameNotFoundException e) {
247                         // Ignore
248                     } catch (NotFoundException e) {
249                         // Ignore
250                     }
251 
252                     // Set the preference title to the activity's label if no
253                     // meta-data is found
254                     if (TextUtils.isEmpty(title)) {
255                         title = resolveInfo.loadLabel(pm).toString();
256                     }
257 
258                     // Set icon, title and summary for the preference
259                     // TODO:
260                     //header.icon = icon;
261                     header.title = title;
262                     header.summary = summary;
263                     // Replace the intent with this specific activity
264                     header.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
265                             resolveInfo.activityInfo.name);
266 
267                     return true;
268                 }
269             }
270         }
271 
272         // Did not find a matching activity, so remove the preference
273         if (target.remove(header)) System.err.println("Removed " + header.id);
274 
275         return false;
276     }
277 
278     /**
279      * Returns true if Monkey is running.
280      */
isMonkeyRunning()281     public static boolean isMonkeyRunning() {
282         return ActivityManager.isUserAMonkey();
283     }
284 
285     /**
286      * Returns whether the device is voice-capable (meaning, it is also a phone).
287      */
isVoiceCapable(Context context)288     public static boolean isVoiceCapable(Context context) {
289         TelephonyManager telephony =
290                 (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
291         return telephony != null && telephony.isVoiceCapable();
292     }
293 
isWifiOnly(Context context)294     public static boolean isWifiOnly(Context context) {
295         ConnectivityManager cm = (ConnectivityManager)context.getSystemService(
296                 Context.CONNECTIVITY_SERVICE);
297         return (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false);
298     }
299 
300     /**
301      * Returns the WIFI IP Addresses, if any, taking into account IPv4 and IPv6 style addresses.
302      * @param context the application context
303      * @return the formatted and comma-separated IP addresses, or null if none.
304      */
getWifiIpAddresses(Context context)305     public static String getWifiIpAddresses(Context context) {
306         ConnectivityManager cm = (ConnectivityManager)
307                 context.getSystemService(Context.CONNECTIVITY_SERVICE);
308         LinkProperties prop = cm.getLinkProperties(ConnectivityManager.TYPE_WIFI);
309         return formatIpAddresses(prop);
310     }
311 
312     /**
313      * Returns the default link's IP addresses, if any, taking into account IPv4 and IPv6 style
314      * addresses.
315      * @param context the application context
316      * @return the formatted and comma-separated IP addresses, or null if none.
317      */
getDefaultIpAddresses(Context context)318     public static String getDefaultIpAddresses(Context context) {
319         ConnectivityManager cm = (ConnectivityManager)
320                 context.getSystemService(Context.CONNECTIVITY_SERVICE);
321         LinkProperties prop = cm.getActiveLinkProperties();
322         return formatIpAddresses(prop);
323     }
324 
formatIpAddresses(LinkProperties prop)325     private static String formatIpAddresses(LinkProperties prop) {
326         if (prop == null) return null;
327         Iterator<InetAddress> iter = prop.getAddresses().iterator();
328         // If there are no entries, return null
329         if (!iter.hasNext()) return null;
330         // Concatenate all available addresses, comma separated
331         String addresses = "";
332         while (iter.hasNext()) {
333             addresses += iter.next().getHostAddress();
334             if (iter.hasNext()) addresses += ", ";
335         }
336         return addresses;
337     }
338 
createLocaleFromString(String localeStr)339     public static Locale createLocaleFromString(String localeStr) {
340         // TODO: is there a better way to actually construct a locale that will match?
341         // The main problem is, on top of Java specs, locale.toString() and
342         // new Locale(locale.toString()).toString() do not return equal() strings in
343         // many cases, because the constructor takes the only string as the language
344         // code. So : new Locale("en", "US").toString() => "en_US"
345         // And : new Locale("en_US").toString() => "en_us"
346         if (null == localeStr)
347             return Locale.getDefault();
348         String[] brokenDownLocale = localeStr.split("_", 3);
349         // split may not return a 0-length array.
350         if (1 == brokenDownLocale.length) {
351             return new Locale(brokenDownLocale[0]);
352         } else if (2 == brokenDownLocale.length) {
353             return new Locale(brokenDownLocale[0], brokenDownLocale[1]);
354         } else {
355             return new Locale(brokenDownLocale[0], brokenDownLocale[1], brokenDownLocale[2]);
356         }
357     }
358 
getBatteryPercentage(Intent batteryChangedIntent)359     public static String getBatteryPercentage(Intent batteryChangedIntent) {
360         int level = batteryChangedIntent.getIntExtra("level", 0);
361         int scale = batteryChangedIntent.getIntExtra("scale", 100);
362         return String.valueOf(level * 100 / scale) + "%";
363     }
364 
getBatteryStatus(Resources res, Intent batteryChangedIntent)365     public static String getBatteryStatus(Resources res, Intent batteryChangedIntent) {
366         final Intent intent = batteryChangedIntent;
367 
368         int plugType = intent.getIntExtra("plugged", 0);
369         int status = intent.getIntExtra("status", BatteryManager.BATTERY_STATUS_UNKNOWN);
370         String statusString;
371         if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
372             statusString = res.getString(R.string.battery_info_status_charging);
373             if (plugType > 0) {
374                 statusString = statusString
375                         + " "
376                         + res.getString((plugType == BatteryManager.BATTERY_PLUGGED_AC)
377                                 ? R.string.battery_info_status_charging_ac
378                                 : R.string.battery_info_status_charging_usb);
379             }
380         } else if (status == BatteryManager.BATTERY_STATUS_DISCHARGING) {
381             statusString = res.getString(R.string.battery_info_status_discharging);
382         } else if (status == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
383             statusString = res.getString(R.string.battery_info_status_not_charging);
384         } else if (status == BatteryManager.BATTERY_STATUS_FULL) {
385             statusString = res.getString(R.string.battery_info_status_full);
386         } else {
387             statusString = res.getString(R.string.battery_info_status_unknown);
388         }
389 
390         return statusString;
391     }
392 
393     /**
394      * Prepare a custom preferences layout, moving padding to {@link ListView}
395      * when outside scrollbars are requested. Usually used to display
396      * {@link ListView} and {@link TabWidget} with correct padding.
397      */
prepareCustomPreferencesList( ViewGroup parent, View child, ListView list, boolean ignoreSidePadding)398     public static void prepareCustomPreferencesList(
399             ViewGroup parent, View child, ListView list, boolean ignoreSidePadding) {
400         final boolean movePadding = list.getScrollBarStyle() == View.SCROLLBARS_OUTSIDE_OVERLAY;
401         if (movePadding && parent instanceof PreferenceFrameLayout) {
402             ((PreferenceFrameLayout.LayoutParams) child.getLayoutParams()).removeBorders = true;
403 
404             final Resources res = list.getResources();
405             final int paddingSide = res.getDimensionPixelSize(
406                     com.android.internal.R.dimen.preference_fragment_padding_side);
407             final int paddingBottom = res.getDimensionPixelSize(
408                     com.android.internal.R.dimen.preference_fragment_padding_bottom);
409 
410             final int effectivePaddingSide = ignoreSidePadding ? 0 : paddingSide;
411             list.setPadding(effectivePaddingSide, 0, effectivePaddingSide, paddingBottom);
412         }
413     }
414 
415     /**
416      * Return string resource that best describes combination of tethering
417      * options available on this device.
418      */
getTetheringLabel(ConnectivityManager cm)419     public static int getTetheringLabel(ConnectivityManager cm) {
420         String[] usbRegexs = cm.getTetherableUsbRegexs();
421         String[] wifiRegexs = cm.getTetherableWifiRegexs();
422         String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
423 
424         boolean usbAvailable = usbRegexs.length != 0;
425         boolean wifiAvailable = wifiRegexs.length != 0;
426         boolean bluetoothAvailable = bluetoothRegexs.length != 0;
427 
428         if (wifiAvailable && usbAvailable && bluetoothAvailable) {
429             return R.string.tether_settings_title_all;
430         } else if (wifiAvailable && usbAvailable) {
431             return R.string.tether_settings_title_all;
432         } else if (wifiAvailable && bluetoothAvailable) {
433             return R.string.tether_settings_title_all;
434         } else if (wifiAvailable) {
435             return R.string.tether_settings_title_wifi;
436         } else if (usbAvailable && bluetoothAvailable) {
437             return R.string.tether_settings_title_usb_bluetooth;
438         } else if (usbAvailable) {
439             return R.string.tether_settings_title_usb;
440         } else {
441             return R.string.tether_settings_title_bluetooth;
442         }
443     }
444 }
445