Fixup: core: Add OmniJawsClient

Cleaned up version from https://github.com/omnirom/android_packages_apps_OmniLib
Keeping it accessible for weather client packages as well as SystemUI package.

Change-Id: Ifadfaa7f4438e3bde52f116f002a7a5273790184

Squashed:

	From: Pranav Vashi <neobuddy89@gmail.com>
	Date: Sat, 7 Sep 2024 21:02:59 +0530
	Subject: [PATCH] OmnijawsClient: Close cursor to avoid memory leak

	From: minaripenguin <minaripenguin@users.noreply.github.com>
	Date: Thu, 12 Sep 2024 21:36:35 +0800
	Subject: [PATCH] OmnijawsClient: Fix memory leak

rmp - do not hold long live context references especially from views, revise memory leak prone practices
neobuddy89 - retain required helper functions

Change-Id: Ie4cccb0eb37197be06595e75729883d078d06541
Co-authored-by: Pranav Vashi <neobuddy89@gmail.com>
Co-authored-by: minaripenguin <minaripenguin@users.noreply.github.com>
Co-authored-by: rmp22 <195054967+rmp22@users.noreply.github.com>
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
Signed-off-by: Dmitrii <bankersenator@gmail.com>
Signed-off-by: MOVZX <movzx@yahoo.com>
This commit is contained in:
maxwen
2025-08-03 17:29:57 +00:00
committed by MOVZX
parent f9784d3729
commit b9a16687f5

View File

@@ -1,27 +1,21 @@
/*
* Copyright (C) 2021 The OmniROM Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.android.internal.util.crdroid;
* Copyright (C) 2021 The OmniROM project
* Copyright (C) 2022-2025 crDroid Android project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
package com.android.internal.util.crdroid;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -30,28 +24,33 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
public class OmniJawsClient {
private static final String TAG = "OmniJawsClient";
private static final boolean DEBUG = false;
public static final String SERVICE_PACKAGE = "org.omnirom.omnijaws";
public static final Uri WEATHER_URI
= Uri.parse("content://org.omnirom.omnijaws.provider/weather");
public static final Uri SETTINGS_URI
= Uri.parse("content://org.omnirom.omnijaws.provider/settings");
public static final Uri CONTROL_URI
= Uri.parse("content://org.omnirom.omnijaws.provider/control");
public static final Uri WEATHER_URI = Uri.parse("content://org.omnirom.omnijaws.provider/weather");
public static final Uri SETTINGS_URI = Uri.parse("content://org.omnirom.omnijaws.provider/settings");
public static final String WEATHER_UPDATE = SERVICE_PACKAGE + ".WEATHER_UPDATE";
public static final String WEATHER_ERROR = SERVICE_PACKAGE + ".WEATHER_ERROR";
private static final String ICON_PACKAGE_DEFAULT = "org.omnirom.omnijaws";
private static final String ICON_PREFIX_DEFAULT = "google_new_light";
@@ -59,39 +58,317 @@ public class OmniJawsClient {
public static final int EXTRA_ERROR_NETWORK = 0;
public static final int EXTRA_ERROR_LOCATION = 1;
public static final int EXTRA_ERROR_DISABLED = 2;
private boolean mWeatherReceiverRegistered;
public static final String[] WEATHER_PROJECTION = new String[]{
"city",
"wind_speed",
"wind_direction",
"condition_code",
"temperature",
"humidity",
"condition",
"forecast_low",
"forecast_high",
"forecast_condition",
"forecast_condition_code",
"time_stamp",
"forecast_date",
"pin_wheel"
public static final String[] WEATHER_PROJECTION = {
"city", "wind_speed", "wind_direction", "condition_code", "temperature",
"humidity", "condition", "forecast_low", "forecast_high", "forecast_condition",
"forecast_condition_code", "time_stamp", "forecast_date", "pin_wheel"
};
public static final String[] SETTINGS_PROJECTION = new String[] {
"enabled",
"units",
"provider",
"setup",
"icon_pack"
public static final String[] SETTINGS_PROJECTION = {
"enabled", "units", "provider", "setup", "icon_pack"
};
private static final String WEATHER_UPDATE = SERVICE_PACKAGE + ".WEATHER_UPDATE";
private static final String WEATHER_ERROR = SERVICE_PACKAGE + ".WEATHER_ERROR";
private static final DecimalFormat sNoDigitsFormat = new DecimalFormat("0");
private static OmniJawsClient sInstance;
private WeatherInfo mCachedInfo;
private Resources mRes;
private String mPackageName;
private String mIconPrefix;
private String mSettingIconPackage;
private boolean mMetric;
private final List<WeakReference<OmniJawsObserver>> mObservers = new ArrayList<>();
private WeatherUpdateReceiver mReceiver;
private boolean mWeatherReceiverRegistered = false;
public static OmniJawsClient get() {
if (sInstance == null) {
synchronized (OmniJawsClient.class) {
if (sInstance == null) {
sInstance = new OmniJawsClient();
}
}
}
return sInstance;
}
public interface OmniJawsObserver {
void weatherUpdated();
void weatherError(int errorReason);
default void updateSettings() {}
}
private class WeatherUpdateReceiver extends BroadcastReceiver {
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
pruneDeadObservers();
for (WeakReference<OmniJawsObserver> ref : mObservers) {
OmniJawsObserver obs = ref.get();
if (obs == null) continue;
if (WEATHER_UPDATE.equals(action)) {
obs.weatherUpdated();
} else if (WEATHER_ERROR.equals(action)) {
obs.weatherError(intent.getIntExtra(EXTRA_ERROR, 0));
}
}
}
}
public Intent getSettingsIntent(Context context) {
if (isOmniJawsEnabled(context)) {
return new Intent(Intent.ACTION_MAIN)
.setClassName(SERVICE_PACKAGE, SERVICE_PACKAGE + ".SettingsActivity");
}
return null;
}
public Intent getWeatherActivityIntent(Context context) {
if (isOmniJawsEnabled(context)) {
return new Intent(Intent.ACTION_MAIN)
.setClassName(SERVICE_PACKAGE, SERVICE_PACKAGE + ".WeatherActivity");
}
return null;
}
public WeatherInfo getWeatherInfo() {
return mCachedInfo;
}
public void queryWeather(Context context) {
if (!isOmniJawsEnabled(context)) {
Log.w(TAG, "queryWeather while disabled");
mCachedInfo = null;
return;
}
try (Cursor weatherCursor = context.getContentResolver().query(
WEATHER_URI, WEATHER_PROJECTION, null, null, null)) {
if (weatherCursor != null && weatherCursor.getCount() > 0) {
mCachedInfo = new WeatherInfo();
List<DayForecast> forecasts = new ArrayList<>();
for (int i = 0; i < weatherCursor.getCount(); i++) {
weatherCursor.moveToPosition(i);
if (i == 0) {
mCachedInfo.city = weatherCursor.getString(0);
mCachedInfo.windSpeed = getFormattedValue(weatherCursor.getFloat(1));
mCachedInfo.windDirection = weatherCursor.getInt(2) + "\u00b0";
mCachedInfo.conditionCode = weatherCursor.getInt(3);
mCachedInfo.temp = getFormattedValue(weatherCursor.getFloat(4));
mCachedInfo.humidity = weatherCursor.getString(5);
mCachedInfo.condition = weatherCursor.getString(6);
mCachedInfo.timeStamp = Long.parseLong(weatherCursor.getString(11));
mCachedInfo.pinWheel = weatherCursor.getString(13);
} else {
DayForecast day = new DayForecast();
day.low = getFormattedValue(weatherCursor.getFloat(7));
day.high = getFormattedValue(weatherCursor.getFloat(8));
day.condition = weatherCursor.getString(9);
day.conditionCode = weatherCursor.getInt(10);
day.date = weatherCursor.getString(12);
forecasts.add(day);
}
}
mCachedInfo.forecasts = forecasts;
}
} catch (Exception e) {
Log.e(TAG, "queryWeather: weather", e);
}
try (Cursor settingsCursor = context.getContentResolver().query(
SETTINGS_URI, SETTINGS_PROJECTION, null, null, null)) {
if (settingsCursor != null && settingsCursor.moveToFirst()) {
mMetric = settingsCursor.getInt(1) == 0;
if (mCachedInfo != null) {
mCachedInfo.tempUnits = getTemperatureUnit();
mCachedInfo.windUnits = getWindUnit();
mCachedInfo.provider = settingsCursor.getString(2);
mCachedInfo.iconPack = settingsCursor.getString(4);
}
}
} catch (Exception e) {
Log.e(TAG, "queryWeather: settings", e);
}
updateSettings(context);
}
private void updateSettings(Context context) {
String iconPack = (mCachedInfo != null) ? mCachedInfo.iconPack : null;
if (iconPack == null || TextUtils.isEmpty(iconPack)) {
loadDefaultIconsPackage(context);
} else if (!iconPack.equals(mSettingIconPackage)) {
mSettingIconPackage = iconPack;
loadCustomIconPackage(context);
}
}
private void loadDefaultIconsPackage(Context context) {
mPackageName = ICON_PACKAGE_DEFAULT;
mIconPrefix = ICON_PREFIX_DEFAULT;
mSettingIconPackage = mPackageName + "." + mIconPrefix;
try {
mRes = context.getPackageManager().getResourcesForApplication(mPackageName);
} catch (Exception e) {
Log.w(TAG, "No default icon package found");
mRes = null;
}
}
private void loadCustomIconPackage(Context context) {
int idx = mSettingIconPackage.lastIndexOf(".");
if (idx == -1) {
loadDefaultIconsPackage(context);
return;
}
mPackageName = mSettingIconPackage.substring(0, idx);
mIconPrefix = mSettingIconPackage.substring(idx + 1);
try {
mRes = context.getPackageManager().getResourcesForApplication(mPackageName);
} catch (Exception e) {
Log.w(TAG, "Icon pack loading failed, fallback to default");
loadDefaultIconsPackage(context);
}
}
private static String getFormattedValue(float value) {
if (Float.isNaN(value)) return "-";
String result = sNoDigitsFormat.format(value);
return result.equals("-0") ? "0" : result;
}
public boolean isOmniJawsServiceInstalled(Context context) {
return isAvailableApp(context, SERVICE_PACKAGE);
}
public boolean isOmniJawsEnabled(Context context) {
if (!isOmniJawsServiceInstalled(context)) return false;
try (Cursor c = context.getContentResolver().query(
SETTINGS_URI, SETTINGS_PROJECTION, null, null, null)) {
return c != null && c.moveToFirst() && c.getInt(0) == 1;
} catch (Exception e) {
Log.e(TAG, "isOmniJawsEnabled", e);
return false;
}
}
private boolean isAvailableApp(Context context, String pkg) {
try {
PackageManager pm = context.getPackageManager();
pm.getPackageInfo(pkg, PackageManager.GET_ACTIVITIES);
int state = pm.getApplicationEnabledSetting(pkg);
return state != PackageManager.COMPONENT_ENABLED_STATE_DISABLED
&& state != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
} catch (NameNotFoundException | IllegalArgumentException e) {
return false;
}
}
public void addObserver(Context context, OmniJawsObserver observer) {
if (observer == null) return;
removeObserver(context, observer);
mObservers.add(new WeakReference<>(observer));
registerReceiverIfNeeded(context);
}
public void removeObserver(Context context, OmniJawsObserver observer) {
if (observer == null) return;
Iterator<WeakReference<OmniJawsObserver>> it = mObservers.iterator();
while (it.hasNext()) {
OmniJawsObserver o = it.next().get();
if (o == null || o == observer) {
it.remove();
}
}
if (mObservers.isEmpty()) {
unregisterReceiver(context);
}
}
private void pruneDeadObservers() {
try {
mObservers.removeIf(ref -> ref.get() == null);
} catch (Exception e) {
Log.w(TAG, "Exception occured while pruning, ignoring");
}
}
private void registerReceiverIfNeeded(Context context) {
if (!mWeatherReceiverRegistered && !mObservers.isEmpty()) {
if (mReceiver != null) {
try {
context.unregisterReceiver(mReceiver);
} catch (Exception ignored) {}
}
mReceiver = new WeatherUpdateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WEATHER_UPDATE);
filter.addAction(WEATHER_ERROR);
context.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);
mWeatherReceiverRegistered = true;
}
}
private void unregisterReceiver(Context context) {
if (mWeatherReceiverRegistered && mReceiver != null) {
try {
context.unregisterReceiver(mReceiver);
} catch (Exception ignored) {}
mWeatherReceiverRegistered = false;
}
}
private String getTemperatureUnit() {
return mMetric ? "\u00b0C" : "\u00b0F";
}
private String getWindUnit() {
return mMetric ? "km/h" : "mph";
}
public Drawable getWeatherConditionImage(Context context, int conditionCode) {
if (mRes == null) {
loadDefaultIconsPackage(context);
}
try {
int resId = mRes.getIdentifier(mIconPrefix + "_" + conditionCode, "drawable", mPackageName);
Drawable d = mRes.getDrawable(resId, null);
return d != null ? d : getDefaultConditionImage(context);
} catch (Exception e) {
Log.e(TAG, "getWeatherConditionImage", e);
return getDefaultConditionImage(context);
}
}
private Drawable getDefaultConditionImage(Context context) {
try {
Resources res = context.getPackageManager().getResourcesForApplication(ICON_PACKAGE_DEFAULT);
int resId = res.getIdentifier(ICON_PREFIX_DEFAULT + "_na", "drawable", ICON_PACKAGE_DEFAULT);
Drawable d = res.getDrawable(resId, null);
return d != null ? d : new ColorDrawable(Color.RED);
} catch (Exception e) {
return new ColorDrawable(Color.RED);
}
}
public Drawable getResOmni(Context context, String iconOmni) {
if (mRes == null) loadDefaultIconsPackage(context);
try {
int resId = mRes.getIdentifier(iconOmni, "drawable", mPackageName);
Drawable d = mRes.getDrawable(resId, null);
return d != null ? d : new ColorDrawable(Color.RED);
} catch (Exception e) {
Log.e(TAG, "getResOmni", e);
return new ColorDrawable(Color.RED);
}
}
public static class WeatherInfo {
public String city;
public String windSpeed;
@@ -108,13 +385,13 @@ public class OmniJawsClient {
public String pinWheel;
public String iconPack;
public String toString() {
return city + ":" + new Date(timeStamp) + ": " + windSpeed + ":" + windDirection + ":" +conditionCode + ":" + temp + ":" + humidity + ":" + condition + ":" + tempUnits + ":" + windUnits + ": " + forecasts + ": " + iconPack;
public String getLastUpdateTime() {
return new SimpleDateFormat("HH:mm:ss", Locale.getDefault()).format(new Date(timeStamp));
}
public String getLastUpdateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
return sdf.format(new Date(timeStamp));
@Override
public String toString() {
return city + " @ " + new Date(timeStamp) + " | " + condition + " | " + temp;
}
}
@@ -125,324 +402,9 @@ public class OmniJawsClient {
public String condition;
public String date;
public String toString() {
return "[" + low + ":" + high + ":" +conditionCode + ":" + condition + ":" + date + "]";
}
}
public static interface OmniJawsObserver {
public void weatherUpdated();
public void weatherError(int errorReason);
default public void updateSettings() {};
}
private class WeatherUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, Intent intent) {
String action = intent.getAction();
for (OmniJawsObserver observer : mObserver) {
if (action.equals(WEATHER_UPDATE)) {
observer.weatherUpdated();
} else if (action.equals(WEATHER_ERROR)) {
int errorReason = intent.getIntExtra(EXTRA_ERROR, 0);
observer.weatherError(errorReason);
}
}
public String toString() {
return "[" + date + " - " + low + "/" + high + " - " + condition + "]";
}
}
private Context mContext;
private WeatherInfo mCachedInfo;
private Resources mRes;
private String mPackageName;
private String mIconPrefix;
private String mSettingIconPackage;
private boolean mMetric;
private List<OmniJawsObserver> mObserver;
private WeatherUpdateReceiver mReceiver;
public OmniJawsClient(Context context) {
mContext = context;
mObserver = new ArrayList<OmniJawsObserver>();
}
public Intent getSettingsIntent() {
if (isOmniJawsServiceInstalled()) {
Intent settings = new Intent(Intent.ACTION_MAIN)
.setClassName(SERVICE_PACKAGE, SERVICE_PACKAGE + ".SettingsActivity");
return settings;
}
return null;
}
public Intent getWeatherActivityIntent() {
if (isOmniJawsServiceInstalled()) {
Intent settings = new Intent(Intent.ACTION_MAIN)
.setClassName(SERVICE_PACKAGE, SERVICE_PACKAGE + ".WeatherActivity");
return settings;
}
return null;
}
public WeatherInfo getWeatherInfo() {
return mCachedInfo;
}
private static String getFormattedValue(float value) {
if (Float.isNaN(value)) {
return "-";
}
String formatted = sNoDigitsFormat.format(value);
if (formatted.equals("-0")) {
formatted = "0";
}
return formatted;
}
public void queryWeather() {
if (!isOmniJawsEnabled()) {
Log.w(TAG, "queryWeather while disabled");
mCachedInfo = null;
return;
}
try {
mCachedInfo = null;
Cursor c = mContext.getContentResolver().query(WEATHER_URI, WEATHER_PROJECTION,
null, null, null);
if (c != null) {
try {
int count = c.getCount();
if (count > 0) {
mCachedInfo = new WeatherInfo();
List<DayForecast> forecastList = new ArrayList<DayForecast>();
int i = 0;
for (i = 0; i < count; i++) {
c.moveToPosition(i);
if (i == 0) {
mCachedInfo.city = c.getString(0);
mCachedInfo.windSpeed = getFormattedValue(c.getFloat(1));
mCachedInfo.windDirection = String.valueOf(c.getInt(2)) + "\u00b0";
mCachedInfo.conditionCode = c.getInt(3);
mCachedInfo.temp = getFormattedValue(c.getFloat(4));
mCachedInfo.humidity = c.getString(5);
mCachedInfo.condition = c.getString(6);
mCachedInfo.timeStamp = Long.valueOf(c.getString(11));
mCachedInfo.pinWheel = c.getString(13);
} else {
DayForecast day = new DayForecast();
day.low = getFormattedValue(c.getFloat(7));
day.high = getFormattedValue(c.getFloat(8));
day.condition = c.getString(9);
day.conditionCode = c.getInt(10);
day.date = c.getString(12);
forecastList.add(day);
}
}
mCachedInfo.forecasts = forecastList;
}
} finally {
c.close();
}
}
c = mContext.getContentResolver().query(SETTINGS_URI, SETTINGS_PROJECTION,
null, null, null);
if (c != null) {
try {
int count = c.getCount();
if (count == 1) {
c.moveToPosition(0);
mMetric = c.getInt(1) == 0;
if (mCachedInfo != null) {
mCachedInfo.tempUnits = getTemperatureUnit();
mCachedInfo.windUnits = getWindUnit();
mCachedInfo.provider = c.getString(2);
mCachedInfo.iconPack = c.getString(4);
}
}
} finally {
c.close();
}
}
if (DEBUG) Log.d(TAG, "queryWeather " + mCachedInfo);
updateSettings();
} catch (Exception e) {
Log.e(TAG, "queryWeather", e);
}
}
private void loadDefaultIconsPackage() {
mPackageName = ICON_PACKAGE_DEFAULT;
mIconPrefix = ICON_PREFIX_DEFAULT;
mSettingIconPackage = mPackageName + "." + mIconPrefix;
if (DEBUG) Log.d(TAG, "Load default icon pack " + mSettingIconPackage + " " + mPackageName + " " + mIconPrefix);
try {
PackageManager packageManager = mContext.getPackageManager();
mRes = packageManager.getResourcesForApplication(mPackageName);
} catch (Exception e) {
mRes = null;
}
if (mRes == null) {
Log.w(TAG, "No default package found");
}
}
private Drawable getDefaultConditionImage() {
String packageName = ICON_PACKAGE_DEFAULT;
String iconPrefix = ICON_PREFIX_DEFAULT;
try {
PackageManager packageManager = mContext.getPackageManager();
Resources res = packageManager.getResourcesForApplication(packageName);
if (res != null) {
int resId = res.getIdentifier(iconPrefix + "_na", "drawable", packageName);
Drawable d = res.getDrawable(resId);
if (d != null) {
return d;
}
}
} catch (Exception e) {
}
// absolute absolute fallback
Log.w(TAG, "No default package found");
return new ColorDrawable(Color.RED);
}
private void loadCustomIconPackage() {
if (DEBUG) Log.d(TAG, "Load custom icon pack " + mSettingIconPackage);
int idx = mSettingIconPackage.lastIndexOf(".");
mPackageName = mSettingIconPackage.substring(0, idx);
mIconPrefix = mSettingIconPackage.substring(idx + 1);
if (DEBUG) Log.d(TAG, "Load custom icon pack " + mPackageName + " " + mIconPrefix);
try {
PackageManager packageManager = mContext.getPackageManager();
mRes = packageManager.getResourcesForApplication(mPackageName);
} catch (Exception e) {
mRes = null;
}
if (mRes == null) {
Log.w(TAG, "Icon pack loading failed - loading default");
loadDefaultIconsPackage();
}
}
public Drawable getWeatherConditionImage(int conditionCode) {
try {
int resId = mRes.getIdentifier(mIconPrefix + "_" + conditionCode, "drawable", mPackageName);
Drawable d = mRes.getDrawable(resId);
if (d != null) {
return d;
}
Log.w(TAG, "Failed to get condition image for " + conditionCode + " use default");
resId = mRes.getIdentifier(mIconPrefix + "_na", "drawable", mPackageName);
d = mRes.getDrawable(resId);
if (d != null) {
return d;
}
} catch(Exception e) {
Log.e(TAG, "getWeatherConditionImage", e);
}
Log.w(TAG, "Failed to get condition image for " + conditionCode);
return getDefaultConditionImage();
}
public boolean isOmniJawsServiceInstalled() {
return isAvailableApp(SERVICE_PACKAGE);
}
public boolean isOmniJawsEnabled() {
if (!isOmniJawsServiceInstalled()) {
return false;
}
boolean enabled = false;
try {
final Cursor c = mContext.getContentResolver().query(SETTINGS_URI, SETTINGS_PROJECTION,
null, null, null);
if (c != null) {
try {
int count = c.getCount();
if (count == 1) {
c.moveToPosition(0);
enabled = c.getInt(0) == 1;
}
} finally {
c.close();
}
}
} catch (Exception e) {
Log.e(TAG, "isOmniJawsEnabled", e);
}
return enabled;
}
private String getTemperatureUnit() {
return "\u00b0" + (mMetric ? "C" : "F");
}
private String getWindUnit() {
return mMetric ? "km/h":"mph";
}
private void updateSettings() {
final String iconPack = mCachedInfo != null ? mCachedInfo.iconPack : null;
if (iconPack == null || TextUtils.isEmpty(iconPack)) {
loadDefaultIconsPackage();
} else if (mSettingIconPackage == null || !iconPack.equals(mSettingIconPackage)) {
mSettingIconPackage = iconPack;
loadCustomIconPackage();
}
}
private boolean isAvailableApp(String packageName) {
final PackageManager pm = mContext.getPackageManager();
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
int enabled = pm.getApplicationEnabledSetting(packageName);
return enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED &&
enabled != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
} catch (NameNotFoundException e) {
return false;
}
}
public void addObserver(OmniJawsObserver observer) {
if (mObserver.contains(observer)) {
removeObserver(observer);
}
mObserver.add(observer);
registerReceiverIfNeeded();
}
public void removeObserver(OmniJawsObserver observer) {
if (mObserver.contains(observer)) {
mObserver.remove(observer);
if (mObserver.isEmpty()) {
unregisterReceiver();
}
}
}
private void registerReceiverIfNeeded() {
if (mObserver.size() == 1 && !mWeatherReceiverRegistered) {
if (mReceiver != null) {
try {
mContext.unregisterReceiver(mReceiver);
} catch (Exception e) {
}
}
mReceiver = new WeatherUpdateReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WEATHER_UPDATE);
filter.addAction(WEATHER_ERROR);
if (DEBUG) Log.d(TAG, "registerReceiver");
mContext.registerReceiver(mReceiver, filter, Context.RECEIVER_EXPORTED);
mWeatherReceiverRegistered = true;
}
}
private void unregisterReceiver() {
if (!mWeatherReceiverRegistered) return;
mContext.unregisterReceiver(mReceiver);
mWeatherReceiverRegistered = false;
}
}