aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuis Vidal <lvidal@cyngn.com>2016-07-15 20:48:45 -0700
committerLuis Vidal <lvidal@cyngn.com>2016-08-12 12:39:15 -0700
commitc487191476cea88ccb6faaa8daa34f40d69fe7e5 (patch)
tree2dc0a0ce2ecad94819790b002426a0d5e067ae51
parentda1776a8a8b21d1ff196c99098b8295240c9326c (diff)
downloadvendor_cmsdk-c487191476cea88ccb6faaa8daa34f40d69fe7e5.zip
vendor_cmsdk-c487191476cea88ccb6faaa8daa34f40d69fe7e5.tar.gz
vendor_cmsdk-c487191476cea88ccb6faaa8daa34f40d69fe7e5.tar.bz2
CMSDK: Broker out WeatherManagerService
Change-Id: I1a2007f626c2943ff2cf5da2ab029250efef56f8
-rw-r--r--cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java515
-rw-r--r--cm/lib/main/java/org/cyanogenmod/platform/internal/WeatherManagerServiceBroker.java114
-rw-r--r--cm/res/AndroidManifest.xml2
-rw-r--r--cm/res/res/values/config.xml2
4 files changed, 116 insertions, 517 deletions
diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java
deleted file mode 100644
index fb22f73..0000000
--- a/cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java
+++ /dev/null
@@ -1,515 +0,0 @@
-/*
- * Copyright (C) 2016 The CyanogenMod 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.
- */
-
-package org.cyanogenmod.platform.internal;
-
-import android.app.AppGlobals;
-import android.content.ComponentName;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteCallbackList;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.Slog;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.os.BackgroundThread;
-import com.android.server.SystemService;
-import cyanogenmod.app.CMContextConstants;
-import cyanogenmod.platform.Manifest;
-import cyanogenmod.providers.CMSettings;
-import cyanogenmod.providers.WeatherContract.WeatherColumns;
-import cyanogenmod.weather.CMWeatherManager;
-import cyanogenmod.weather.ICMWeatherManager;
-import cyanogenmod.weather.IRequestInfoListener;
-import cyanogenmod.weather.IWeatherServiceProviderChangeListener;
-import cyanogenmod.weather.RequestInfo;
-import cyanogenmod.weather.WeatherInfo;
-import cyanogenmod.weatherservice.IWeatherProviderService;
-import cyanogenmod.weatherservice.IWeatherProviderServiceClient;
-import cyanogenmod.weatherservice.ServiceRequestResult;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class CMWeatherManagerService extends CMSystemService {
-
- private static final String TAG = CMWeatherManagerService.class.getSimpleName();
-
- private IWeatherProviderService mWeatherProviderService;
- private boolean mIsWeatherProviderServiceBound;
- private Object mMutex = new Object();
- private Context mContext;
- private final RemoteCallbackList<IWeatherServiceProviderChangeListener> mProviderChangeListeners
- = new RemoteCallbackList<>();
- private volatile boolean mReconnectedDuePkgModified = false;
-
- private final IWeatherProviderServiceClient mServiceClient
- = new IWeatherProviderServiceClient.Stub() {
- @Override
- public void setServiceRequestState(RequestInfo requestInfo,
- ServiceRequestResult result, int status) {
- synchronized (mMutex) {
-
- if (requestInfo == null) {
- //Invalid request info object
- return;
- }
-
- if (!isValidRequestInfoStatus(status)) {
- //Invalid request status
- return;
- }
-
- final IRequestInfoListener listener = requestInfo.getRequestListener();
- final int requestType = requestInfo.getRequestType();
-
- switch (requestType) {
- case RequestInfo.TYPE_WEATHER_BY_GEO_LOCATION_REQ:
- case RequestInfo.TYPE_WEATHER_BY_WEATHER_LOCATION_REQ:
- WeatherInfo weatherInfo = null;
- if (status == CMWeatherManager.RequestStatus.COMPLETED) {
- weatherInfo = (result != null) ? result.getWeatherInfo() : null;
- if (weatherInfo == null) {
- //This should never happen! WEATHER_REQUEST_COMPLETED is set
- //only if the weatherinfo object was not null when the request
- //was marked as completed
- status = CMWeatherManager.RequestStatus.FAILED;
- } else {
- if (!requestInfo.isQueryOnlyWeatherRequest()) {
- final long identity = Binder.clearCallingIdentity();
- try {
- updateWeatherInfoLocked(weatherInfo);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
- }
- }
- if (isValidListener(listener)) {
- try {
- listener.onWeatherRequestCompleted(requestInfo, status,
- weatherInfo);
- } catch (RemoteException e) {
- }
- }
- break;
- case RequestInfo.TYPE_LOOKUP_CITY_NAME_REQ:
- if (isValidListener(listener)) {
- try {
- //Result might be null if the provider marked the request as failed
- listener.onLookupCityRequestCompleted(requestInfo, status,
- result != null ? result.getLocationLookupList() : null);
- } catch (RemoteException e) {
- }
- }
- break;
- }
- }
- }
- };
-
- private boolean isValidRequestInfoStatus(int state) {
- switch (state) {
- case CMWeatherManager.RequestStatus.COMPLETED:
- case CMWeatherManager.RequestStatus.ALREADY_IN_PROGRESS:
- case CMWeatherManager.RequestStatus.FAILED:
- case CMWeatherManager.RequestStatus.NO_MATCH_FOUND:
- case CMWeatherManager.RequestStatus.SUBMITTED_TOO_SOON:
- return true;
- default:
- return false;
- }
- }
-
- private boolean isValidListener(IRequestInfoListener listener) {
- return (listener != null && listener.asBinder().pingBinder());
- }
-
- private void enforcePermission() {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.ACCESS_WEATHER_MANAGER, null);
- }
-
- private final IBinder mService = new ICMWeatherManager.Stub() {
-
- @Override
- public void updateWeather(RequestInfo info) {
- enforcePermission();
- processWeatherUpdateRequest(info);
- }
-
- @Override
- public void lookupCity(RequestInfo info) {
- enforcePermission();
- processCityNameLookupRequest(info);
- }
-
- @Override
- public void registerWeatherServiceProviderChangeListener(
- IWeatherServiceProviderChangeListener listener) {
- enforcePermission();
- mProviderChangeListeners.register(listener);
- }
-
- @Override
- public void unregisterWeatherServiceProviderChangeListener(
- IWeatherServiceProviderChangeListener listener) {
- enforcePermission();
- mProviderChangeListeners.unregister(listener);
- }
-
- @Override
- public String getActiveWeatherServiceProviderLabel() {
- enforcePermission();
- final long identity = Binder.clearCallingIdentity();
- try {
- String enabledProviderService = CMSettings.Secure.getString(
- mContext.getContentResolver(), CMSettings.Secure.WEATHER_PROVIDER_SERVICE);
- if (enabledProviderService != null) {
- return getComponentLabel(
- ComponentName.unflattenFromString(enabledProviderService));
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- return null;
- }
-
- @Override
- public void cancelRequest(int requestId) {
- enforcePermission();
- processCancelRequest(requestId);
- }
- };
-
- private String getComponentLabel(ComponentName componentName) {
- final PackageManager pm = mContext.getPackageManager();
- Intent intent = new Intent().setComponent(componentName);
- ResolveInfo resolveInfo = pm.resolveService(intent,
- PackageManager.GET_SERVICES);
- if (resolveInfo != null) {
- return resolveInfo.loadLabel(pm).toString();
- }
- return null;
- }
-
- public CMWeatherManagerService(Context context) {
- super(context);
- mContext = context;
- }
-
- @Override
- public String getFeatureDeclaration() {
- return CMContextConstants.Features.WEATHER_SERVICES;
- }
-
- @Override
- public void onStart() {
- publishBinderService(CMContextConstants.CM_WEATHER_SERVICE, mService);
- registerPackageMonitor();
- registerSettingsObserver();
- }
-
- @Override
- public void onBootPhase(int phase) {
- if (phase == PHASE_ACTIVITY_MANAGER_READY) {
- bindActiveWeatherProviderService();
- }
- }
-
- private void bindActiveWeatherProviderService() {
- String activeProviderService = CMSettings.Secure.getString(mContext.getContentResolver(),
- CMSettings.Secure.WEATHER_PROVIDER_SERVICE);
- if (activeProviderService != null) {
- if (!getContext().bindServiceAsUser(new Intent().setComponent(
- ComponentName.unflattenFromString(activeProviderService)),
- mWeatherServiceProviderConnection, Context.BIND_AUTO_CREATE,
- UserHandle.CURRENT)) {
- Slog.w(TAG, "Failed to bind service " + activeProviderService);
- }
- }
- }
-
- private boolean canProcessWeatherUpdateRequest(RequestInfo info) {
- final IRequestInfoListener listener = info.getRequestListener();
-
- if (!mIsWeatherProviderServiceBound) {
- if (listener != null && listener.asBinder().pingBinder()) {
- try {
- listener.onWeatherRequestCompleted(info,
- CMWeatherManager.RequestStatus.FAILED, null);
- } catch (RemoteException e) {
- }
- }
- return false;
- }
- return true;
- }
-
- private synchronized void processWeatherUpdateRequest(RequestInfo info) {
- if (!canProcessWeatherUpdateRequest(info)) return;
- try {
- mWeatherProviderService.processWeatherUpdateRequest(info);
- } catch (RemoteException e) {
- }
- }
-
- private void processCityNameLookupRequest(RequestInfo info) {
- if (!mIsWeatherProviderServiceBound) {
- final IRequestInfoListener listener = info.getRequestListener();
- if (listener != null && listener.asBinder().pingBinder()) {
- try {
- listener.onLookupCityRequestCompleted(info,
- CMWeatherManager.RequestStatus.FAILED, null);
- } catch (RemoteException e) {
- }
- }
- return;
- }
- try {
- mWeatherProviderService.processCityNameLookupRequest(info);
- } catch(RemoteException e){
- }
- }
-
- private void processCancelRequest(int requestId) {
- if (mIsWeatherProviderServiceBound) {
- try {
- mWeatherProviderService.cancelRequest(requestId);
- } catch (RemoteException e) {
- }
- }
- }
-
- private ServiceConnection mWeatherServiceProviderConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mWeatherProviderService = IWeatherProviderService.Stub.asInterface(service);
- mIsWeatherProviderServiceBound = true;
- try {
- mWeatherProviderService.setServiceClient(mServiceClient);
- } catch(RemoteException e) {
- }
- if (!mReconnectedDuePkgModified) {
- notifyProviderChanged(name);
- }
- mReconnectedDuePkgModified = false;
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mWeatherProviderService = null;
- mIsWeatherProviderServiceBound = false;
- Slog.d(TAG, "Connection with " + name.flattenToString() + " has been closed");
- }
- };
-
- private void notifyProviderChanged(ComponentName name) {
- String providerName = null;
- if (name != null) {
- providerName = getComponentLabel(name);
- }
-
- int N = mProviderChangeListeners.beginBroadcast();
- for (int indx = 0; indx < N; indx++) {
- IWeatherServiceProviderChangeListener listener
- = mProviderChangeListeners.getBroadcastItem(indx);
- try {
- listener.onWeatherServiceProviderChanged(providerName);
- } catch (RemoteException e){
- }
- }
- mProviderChangeListeners.finishBroadcast();
- }
-
- private boolean updateWeatherInfoLocked(WeatherInfo wi) {
- final int size = wi.getForecasts().size() + 1;
- List<ContentValues> contentValuesList = new ArrayList<>(size);
- ContentValues contentValues = new ContentValues();
-
- contentValues.put(WeatherColumns.CURRENT_CITY, wi.getCity());
- contentValues.put(WeatherColumns.CURRENT_TEMPERATURE, wi.getTemperature());
- contentValues.put(WeatherColumns.CURRENT_TEMPERATURE_UNIT, wi.getTemperatureUnit());
- contentValues.put(WeatherColumns.CURRENT_CONDITION_CODE, wi.getConditionCode());
- contentValues.put(WeatherColumns.CURRENT_HUMIDITY, wi.getHumidity());
- contentValues.put(WeatherColumns.CURRENT_WIND_SPEED, wi.getWindSpeed());
- contentValues.put(WeatherColumns.CURRENT_WIND_DIRECTION, wi.getWindDirection());
- contentValues.put(WeatherColumns.CURRENT_WIND_SPEED_UNIT, wi.getWindSpeedUnit());
- contentValues.put(WeatherColumns.CURRENT_TIMESTAMP, wi.getTimestamp());
- contentValues.put(WeatherColumns.TODAYS_HIGH_TEMPERATURE, wi.getTodaysHigh());
- contentValues.put(WeatherColumns.TODAYS_LOW_TEMPERATURE, wi.getTodaysLow());
- contentValuesList.add(contentValues);
-
- for (WeatherInfo.DayForecast df : wi.getForecasts()) {
- contentValues = new ContentValues();
- contentValues.put(WeatherColumns.FORECAST_LOW, df.getLow());
- contentValues.put(WeatherColumns.FORECAST_HIGH, df.getHigh());
- contentValues.put(WeatherColumns.FORECAST_CONDITION_CODE, df.getConditionCode());
- contentValuesList.add(contentValues);
- }
-
- ContentValues[] updateValues = new ContentValues[contentValuesList.size()];
- if (size != getContext().getContentResolver().bulkInsert(
- WeatherColumns.CURRENT_AND_FORECAST_WEATHER_URI,
- contentValuesList.toArray(updateValues))) {
- Slog.w(TAG, "Failed to update the weather content provider");
- return false;
- }
- return true;
- }
-
- private void registerPackageMonitor() {
- PackageMonitor monitor = new PackageMonitor() {
- @Override
- public void onPackageModified(String packageName) {
- String enabledProviderService = CMSettings.Secure.getString(
- mContext.getContentResolver(), CMSettings.Secure.WEATHER_PROVIDER_SERVICE);
- if (enabledProviderService == null) return;
- ComponentName cn = ComponentName.unflattenFromString(enabledProviderService);
- if (!TextUtils.equals(packageName, cn.getPackageName())) return;
-
- if (cn.getPackageName().equals(packageName) && !mIsWeatherProviderServiceBound) {
- //We were disconnected because the whole package changed
- //(most likely remove->install)
- if (!getContext().bindServiceAsUser(new Intent().setComponent(cn),
- mWeatherServiceProviderConnection, Context.BIND_AUTO_CREATE,
- UserHandle.CURRENT)) {
- CMSettings.Secure.putStringForUser( mContext.getContentResolver(),
- CMSettings.Secure.WEATHER_PROVIDER_SERVICE, null,
- getChangingUserId());
- Slog.w(TAG, "Unable to rebind " + cn.flattenToString() + " after receiving"
- + " package modified notification. Settings updated.");
- } else {
- mReconnectedDuePkgModified = true;
- }
- }
- }
-
- @Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
- String enabledProviderService = CMSettings.Secure.getString(
- mContext.getContentResolver(), CMSettings.Secure.WEATHER_PROVIDER_SERVICE);
- if (enabledProviderService == null) return false;
-
- boolean packageChanged = false;
- ComponentName cn = ComponentName.unflattenFromString(enabledProviderService);
- for (String component : components) {
- if (cn.getPackageName().equals(component)) {
- packageChanged = true;
- break;
- }
- }
-
- if (packageChanged) {
- try {
- final IPackageManager pm = AppGlobals.getPackageManager();
- final int enabled = pm.getApplicationEnabledSetting(packageName,
- getChangingUserId());
- if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) {
- return false;
- } else {
- disconnectClient();
- //The package is not enabled so we can't use it anymore
- CMSettings.Secure.putStringForUser(
- mContext.getContentResolver(),
- CMSettings.Secure.WEATHER_PROVIDER_SERVICE, null,
- getChangingUserId());
- Slog.w(TAG, "Active provider " + cn.flattenToString() + " disabled");
- notifyProviderChanged(null);
- }
- } catch (IllegalArgumentException e) {
- Slog.d(TAG, "Exception trying to look up app enabled settings ", e);
- } catch (RemoteException e) {
- // Really?
- }
- }
- return false;
- }
-
- @Override
- public void onPackageRemoved(String packageName, int uid) {
- String enabledProviderService = CMSettings.Secure.getString(
- mContext.getContentResolver(), CMSettings.Secure.WEATHER_PROVIDER_SERVICE);
- if (enabledProviderService == null) return;
-
- ComponentName cn = ComponentName.unflattenFromString(enabledProviderService);
- if (!TextUtils.equals(packageName, cn.getPackageName())) return;
-
- disconnectClient();
- CMSettings.Secure.putStringForUser(
- mContext.getContentResolver(), CMSettings.Secure.WEATHER_PROVIDER_SERVICE,
- null, getChangingUserId());
- notifyProviderChanged(null);
- }
- };
-
- monitor.register(mContext, BackgroundThread.getHandler().getLooper(), UserHandle.ALL, true);
- }
-
- private void registerSettingsObserver() {
- final Uri enabledWeatherProviderServiceUri = CMSettings.Secure.getUriFor(
- CMSettings.Secure.WEATHER_PROVIDER_SERVICE);
- ContentObserver observer = new ContentObserver(BackgroundThread.getHandler()) {
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- if (enabledWeatherProviderServiceUri.equals(uri)) {
- String activeSrvc = CMSettings.Secure.getString(mContext.getContentResolver(),
- CMSettings.Secure.WEATHER_PROVIDER_SERVICE);
- disconnectClient();
- if (activeSrvc != null) {
- ComponentName cn = ComponentName.unflattenFromString(activeSrvc);
- getContext().bindServiceAsUser(new Intent().setComponent(cn),
- mWeatherServiceProviderConnection, Context.BIND_AUTO_CREATE,
- UserHandle.CURRENT);
- }
- }
- }
- };
- mContext.getContentResolver().registerContentObserver(enabledWeatherProviderServiceUri,
- false, observer, UserHandle.USER_ALL);
- }
-
- private synchronized void disconnectClient() {
- if (mIsWeatherProviderServiceBound) {
- //let's cancel any pending request
- try {
- mWeatherProviderService.cancelOngoingRequests();
- } catch (RemoteException e) {
- Slog.d(TAG, "Error occurred while trying to cancel ongoing requests");
- }
- //Disconnect from client
- try {
- mWeatherProviderService.setServiceClient(null);
- } catch (RemoteException e) {
- Slog.d(TAG, "Error occurred while disconnecting client");
- }
-
- getContext().unbindService(mWeatherServiceProviderConnection);
- mIsWeatherProviderServiceBound = false;
- }
- }
-}
diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/WeatherManagerServiceBroker.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/WeatherManagerServiceBroker.java
new file mode 100644
index 0000000..83ce801
--- /dev/null
+++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/WeatherManagerServiceBroker.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 The CyanogenMod 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.
+ */
+
+package org.cyanogenmod.platform.internal;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import cyanogenmod.app.CMContextConstants;
+import cyanogenmod.platform.Manifest;
+import cyanogenmod.weather.ICMWeatherManager;
+import cyanogenmod.weather.IWeatherServiceProviderChangeListener;
+import cyanogenmod.weather.RequestInfo;
+
+public class WeatherManagerServiceBroker extends BrokerableCMSystemService<ICMWeatherManager> {
+
+ private Context mContext;
+
+ private static final ComponentName TARGET_IMPLEMENTATION_COMPONENT =
+ new ComponentName("org.cyanogenmod.weatherservice",
+ "org.cyanogenmod.weatherservice.WeatherManagerService");
+
+ private void enforcePermission() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.ACCESS_WEATHER_MANAGER, null);
+ }
+
+ private final IBinder mService = new ICMWeatherManager.Stub() {
+
+ @Override
+ public void updateWeather(RequestInfo info) throws RemoteException {
+ enforcePermission();
+ getBrokeredService().updateWeather(info);
+ }
+
+ @Override
+ public void lookupCity(RequestInfo info) throws RemoteException {
+ enforcePermission();
+ getBrokeredService().lookupCity(info);
+ }
+
+ @Override
+ public void registerWeatherServiceProviderChangeListener(
+ IWeatherServiceProviderChangeListener listener) throws RemoteException {
+ enforcePermission();
+ getBrokeredService().registerWeatherServiceProviderChangeListener(listener);
+ }
+
+ @Override
+ public void unregisterWeatherServiceProviderChangeListener(
+ IWeatherServiceProviderChangeListener listener) throws RemoteException {
+ enforcePermission();
+ getBrokeredService().unregisterWeatherServiceProviderChangeListener(listener);
+ }
+
+ @Override
+ public String getActiveWeatherServiceProviderLabel() throws RemoteException {
+ enforcePermission();
+ return getBrokeredService().getActiveWeatherServiceProviderLabel();
+ }
+
+ @Override
+ public void cancelRequest(int requestId) throws RemoteException {
+ enforcePermission();
+ getBrokeredService().cancelRequest(requestId);
+ }
+ };
+
+ public WeatherManagerServiceBroker(Context context) {
+ super(context);
+ mContext = context;
+ }
+
+ @Override
+ public String getFeatureDeclaration() {
+ return CMContextConstants.Features.WEATHER_SERVICES;
+ }
+
+ @Override
+ public void onStart() {
+ publishBinderService(CMContextConstants.CM_WEATHER_SERVICE, mService);
+ }
+
+ @Override
+ protected ICMWeatherManager getIBinderAsIInterface(@NonNull IBinder service) {
+ return ICMWeatherManager.Stub.asInterface(service);
+ }
+
+ @Override
+ protected ICMWeatherManager getDefaultImplementation() {
+ return new ICMWeatherManager.NoOp();
+ }
+
+ @Override
+ protected ComponentName getServiceComponent() {
+ return TARGET_IMPLEMENTATION_COMPONENT;
+ }
+
+}
diff --git a/cm/res/AndroidManifest.xml b/cm/res/AndroidManifest.xml
index 3e23af3..8eee210 100644
--- a/cm/res/AndroidManifest.xml
+++ b/cm/res/AndroidManifest.xml
@@ -212,7 +212,7 @@
<permission android:name="cyanogenmod.permission.BIND_WEATHER_PROVIDER_SERVICE"
android:label="@string/permlab_weather_bind"
android:description="@string/permdesc_weather_bind"
- android:protectionLevel="signature"/>
+ android:protectionLevel="signature|privileged"/>
<!-- Allows an application to observe system-wide changes to audio sessions
@hide -->
diff --git a/cm/res/res/values/config.xml b/cm/res/res/values/config.xml
index 1b0d6a8..1252122 100644
--- a/cm/res/res/values/config.xml
+++ b/cm/res/res/values/config.xml
@@ -122,7 +122,7 @@
<item>org.cyanogenmod.platform.internal.ThemeManagerServiceBroker</item>
<item>org.cyanogenmod.platform.internal.IconCacheManagerServiceBroker</item>
<item>org.cyanogenmod.platform.internal.LiveLockScreenServiceBroker</item>
- <item>org.cyanogenmod.platform.internal.CMWeatherManagerService</item>
+ <item>org.cyanogenmod.platform.internal.WeatherManagerServiceBroker</item>
<item>org.cyanogenmod.platform.internal.display.LiveDisplayService</item>
<item>org.cyanogenmod.platform.internal.CMAudioServiceBroker</item>
</string-array>