From ad0d8c53a0987e5877df5dfe30b7b7025cefffd0 Mon Sep 17 00:00:00 2001 From: Luis Vidal Date: Tue, 12 Apr 2016 18:24:27 -0700 Subject: [PATCH] Weather API: Return ID rather than RequestInfo [1/2] Instead of exposing the RequestInfo object created by the WeatherMgr return an ID to identify the request. This ID can be later used to cancel the request if needed. The WeatherProviderService base class keeps track of the ongoing requests and can map this ID to the corresponding request This patch also include the following minor changes: - Use List instead of ArrayList in API - Update javadoc to public methods to reflect API changes - Use UUID random generator in immutable classes to generate the hashcode rather than relying solely in the hashcode of the builder object. Change-Id: Ib88dd0ecddd6fdb016b77ac29709fbae092dea29 TICKET: CYNGNOS-2425 TICKET: CYNGNOS-2423 --- api/cm_current.txt | 24 +++--- .../internal/CMWeatherManagerService.java | 8 +- .../cyanogenmod/weather/CMWeatherManager.java | 53 ++++++------- .../weather/ICMWeatherManager.aidl | 2 +- .../java/cyanogenmod/weather/RequestInfo.java | 30 +++++--- .../java/cyanogenmod/weather/WeatherInfo.java | 57 +++++++------- .../cyanogenmod/weather/WeatherLocation.java | 67 +++++++++++----- .../IWeatherProviderService.aidl | 2 +- .../weatherservice/ServiceRequestResult.java | 77 ++++++++----------- .../WeatherProviderService.java | 63 ++++++--------- system-api/cm_system-current.txt | 24 +++--- 11 files changed, 210 insertions(+), 197 deletions(-) diff --git a/api/cm_current.txt b/api/cm_current.txt index 5992f3f..f3b5536 100644 --- a/api/cm_current.txt +++ b/api/cm_current.txt @@ -1351,13 +1351,13 @@ package cyanogenmod.util { package cyanogenmod.weather { public class CMWeatherManager { - method public void cancelRequest(cyanogenmod.weather.RequestInfo); + method public void cancelRequest(int); method public java.lang.String getActiveWeatherServiceProviderLabel(); method public static cyanogenmod.weather.CMWeatherManager getInstance(android.content.Context); - method public cyanogenmod.weather.RequestInfo lookupCity(java.lang.String, cyanogenmod.weather.CMWeatherManager.LookupCityRequestListener); + method public int lookupCity(java.lang.String, cyanogenmod.weather.CMWeatherManager.LookupCityRequestListener); method public void registerWeatherServiceProviderChangeListener(cyanogenmod.weather.CMWeatherManager.WeatherServiceProviderChangeListener); - method public cyanogenmod.weather.RequestInfo requestWeatherUpdate(android.location.Location, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); - method public cyanogenmod.weather.RequestInfo requestWeatherUpdate(cyanogenmod.weather.WeatherLocation, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); + method public int requestWeatherUpdate(android.location.Location, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); + method public int requestWeatherUpdate(cyanogenmod.weather.WeatherLocation, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); method public void unregisterWeatherServiceProviderChangeListener(cyanogenmod.weather.CMWeatherManager.WeatherServiceProviderChangeListener); field public static final int WEATHER_REQUEST_ALREADY_IN_PROGRESS = -3; // 0xfffffffd field public static final int WEATHER_REQUEST_COMPLETED = 1; // 0x1 @@ -1366,7 +1366,7 @@ package cyanogenmod.weather { } public static abstract interface CMWeatherManager.LookupCityRequestListener { - method public abstract void onLookupCityRequestCompleted(java.util.ArrayList); + method public abstract void onLookupCityRequestCompleted(java.util.List); } public static abstract interface CMWeatherManager.WeatherServiceProviderChangeListener { @@ -1395,7 +1395,7 @@ package cyanogenmod.weather { method public int describeContents(); method public java.lang.String getCity(); method public int getConditionCode(); - method public java.util.ArrayList getForecasts(); + method public java.util.List getForecasts(); method public double getHumidity(); method public double getTemperature(); method public int getTemperatureUnit(); @@ -1412,7 +1412,7 @@ package cyanogenmod.weather { public static class WeatherInfo.Builder { ctor public WeatherInfo.Builder(java.lang.String, double, int); method public cyanogenmod.weather.WeatherInfo build(); - method public cyanogenmod.weather.WeatherInfo.Builder setForecast(java.util.ArrayList); + method public cyanogenmod.weather.WeatherInfo.Builder setForecast(java.util.List); method public cyanogenmod.weather.WeatherInfo.Builder setHumidity(double); method public cyanogenmod.weather.WeatherInfo.Builder setTimestamp(long); method public cyanogenmod.weather.WeatherInfo.Builder setTodaysHigh(double); @@ -1451,8 +1451,10 @@ package cyanogenmod.weather { public static class WeatherLocation.Builder { ctor public WeatherLocation.Builder(java.lang.String, java.lang.String); + ctor public WeatherLocation.Builder(java.lang.String); method public cyanogenmod.weather.WeatherLocation build(); - method public cyanogenmod.weather.WeatherLocation.Builder setCountry(java.lang.String, java.lang.String); + method public cyanogenmod.weather.WeatherLocation.Builder setCountry(java.lang.String); + method public cyanogenmod.weather.WeatherLocation.Builder setCountryId(java.lang.String); method public cyanogenmod.weather.WeatherLocation.Builder setPostalCode(java.lang.String); method public cyanogenmod.weather.WeatherLocation.Builder setState(java.lang.String); } @@ -1469,7 +1471,7 @@ package cyanogenmod.weatherservice { public final class ServiceRequestResult implements android.os.Parcelable { method public int describeContents(); - method public java.util.ArrayList getLocationLookupList(); + method public java.util.List getLocationLookupList(); method public cyanogenmod.weather.WeatherInfo getWeatherInfo(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -1477,9 +1479,9 @@ package cyanogenmod.weatherservice { public static class ServiceRequestResult.Builder { ctor public ServiceRequestResult.Builder(); + ctor public ServiceRequestResult.Builder(cyanogenmod.weather.WeatherInfo); + ctor public ServiceRequestResult.Builder(java.util.List); method public cyanogenmod.weatherservice.ServiceRequestResult build(); - method public cyanogenmod.weatherservice.ServiceRequestResult.Builder setLocationLookupList(java.util.ArrayList); - method public cyanogenmod.weatherservice.ServiceRequestResult.Builder setWeatherInfo(cyanogenmod.weather.WeatherInfo); } public abstract class WeatherProviderService extends android.app.Service { diff --git a/cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java b/cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java index cf79c9b..69392fd 100644 --- a/cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java +++ b/cm/lib/main/java/org/cyanogenmod/platform/internal/CMWeatherManagerService.java @@ -222,9 +222,9 @@ public class CMWeatherManagerService extends SystemService{ } @Override - public void cancelRequest(RequestInfo info) { + public void cancelRequest(int requestId) { enforcePermission(); - processCancelRequest(info); + processCancelRequest(requestId); } }; @@ -340,10 +340,10 @@ public class CMWeatherManagerService extends SystemService{ } } - private void processCancelRequest(RequestInfo info) { + private void processCancelRequest(int requestId) { if (mIsWeatherProviderServiceBound) { try { - mWeatherProviderService.cancelRequest(info); + mWeatherProviderService.cancelRequest(requestId); } catch (RemoteException e) { } } diff --git a/sdk/src/java/cyanogenmod/weather/CMWeatherManager.java b/sdk/src/java/cyanogenmod/weather/CMWeatherManager.java index 3ab510e..2613ea5 100644 --- a/sdk/src/java/cyanogenmod/weather/CMWeatherManager.java +++ b/sdk/src/java/cyanogenmod/weather/CMWeatherManager.java @@ -131,14 +131,14 @@ public class CMWeatherManager { * @param listener {@link WeatherUpdateRequestListener} To be notified once the active weather * service provider has finished * processing your request - * @return A {@link RequestInfo} identifying the request submitted to the weather service. - * Note that this method might return null if an error occurred while trying to submit + * @return An integer that identifies the request submitted to the weather service + * Note that this method might return -1 if an error occurred while trying to submit * the request. */ - public RequestInfo requestWeatherUpdate(@NonNull Location location, + public int requestWeatherUpdate(@NonNull Location location, @NonNull WeatherUpdateRequestListener listener) { if (sWeatherManagerService == null) { - return null; + return -1; } try { @@ -148,9 +148,9 @@ public class CMWeatherManager { .build(); if (listener != null) mWeatherUpdateRequestListeners.put(info, listener); sWeatherManagerService.updateWeather(info); - return info; + return info.hashCode(); } catch (RemoteException e) { - return null; + return -1; } } @@ -164,14 +164,14 @@ public class CMWeatherManager { * @param listener {@link WeatherUpdateRequestListener} To be notified once the active weather * service provider has finished * processing your request - * @return A {@link RequestInfo} identifying the request submitted to the weather service. - * Note that this method might return null if an error occurred while trying to submit + * @return An integer that identifies the request submitted to the weather service. + * Note that this method might return -1 if an error occurred while trying to submit * the request. */ - public RequestInfo requestWeatherUpdate(@NonNull WeatherLocation weatherLocation, + public int requestWeatherUpdate(@NonNull WeatherLocation weatherLocation, @NonNull WeatherUpdateRequestListener listener) { if (sWeatherManagerService == null) { - return null; + return -1; } try { @@ -181,9 +181,9 @@ public class CMWeatherManager { .build(); if (listener != null) mWeatherUpdateRequestListeners.put(info, listener); sWeatherManagerService.updateWeather(info); - return info; + return info.hashCode(); } catch (RemoteException e) { - return null; + return -1; } } @@ -195,13 +195,13 @@ public class CMWeatherManager { * completed. Upon success, a list of * {@link cyanogenmod.weather.WeatherLocation} * will be provided - * @return A {@link RequestInfo} identifying the request submitted to the weather service. - * Note that this method might return null if an error occurred while trying to submit + * @return An integer that identifies the request submitted to the weather service. + * Note that this method might return -1 if an error occurred while trying to submit * the request. */ - public RequestInfo lookupCity(@NonNull String city, @NonNull LookupCityRequestListener listener) { + public int lookupCity(@NonNull String city, @NonNull LookupCityRequestListener listener) { if (sWeatherManagerService == null) { - return null; + return -1; } try { RequestInfo info = new RequestInfo @@ -210,26 +210,23 @@ public class CMWeatherManager { .build(); if (listener != null) mLookupNameRequestListeners.put(info, listener); sWeatherManagerService.lookupCity(info); - return info; + return info.hashCode(); } catch (RemoteException e) { - return null; + return -1; } } /** * Cancels a request that was previously submitted to the weather service. - * @param info The {@link RequestInfo} that you received when the request was submitted + * @param requestId The ID that you received when the request was submitted */ - public void cancelRequest(RequestInfo info) { + public void cancelRequest(int requestId) { if (sWeatherManagerService == null) { return; } - if (info == null) { - return; - } try { - sWeatherManagerService.cancelRequest(info); + sWeatherManagerService.cancelRequest(requestId); }catch (RemoteException e){ } } @@ -345,11 +342,7 @@ public class CMWeatherManager { mHandler.post(new Runnable() { @Override public void run() { - ArrayList list = null; - if (weatherLocations != null) { - list = new ArrayList<>(weatherLocations); - } - listener.onLookupCityRequestCompleted(list); + listener.onLookupCityRequestCompleted(weatherLocations); } }); } @@ -386,7 +379,7 @@ public class CMWeatherManager { * * @param locations */ - void onLookupCityRequestCompleted(ArrayList locations); + void onLookupCityRequestCompleted(List locations); } /** diff --git a/sdk/src/java/cyanogenmod/weather/ICMWeatherManager.aidl b/sdk/src/java/cyanogenmod/weather/ICMWeatherManager.aidl index 8caac49..c933ae6 100644 --- a/sdk/src/java/cyanogenmod/weather/ICMWeatherManager.aidl +++ b/sdk/src/java/cyanogenmod/weather/ICMWeatherManager.aidl @@ -28,5 +28,5 @@ interface ICMWeatherManager { oneway void unregisterWeatherServiceProviderChangeListener( in IWeatherServiceProviderChangeListener listener); String getActiveWeatherServiceProviderLabel(); - oneway void cancelRequest(in RequestInfo info); + oneway void cancelRequest(int requestId); } \ No newline at end of file diff --git a/sdk/src/java/cyanogenmod/weather/RequestInfo.java b/sdk/src/java/cyanogenmod/weather/RequestInfo.java index bb05301..44805a2 100644 --- a/sdk/src/java/cyanogenmod/weather/RequestInfo.java +++ b/sdk/src/java/cyanogenmod/weather/RequestInfo.java @@ -20,11 +20,14 @@ import android.location.Location; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import cyanogenmod.os.Build; import cyanogenmod.os.Concierge; import cyanogenmod.os.Concierge.ParcelInfo; import cyanogenmod.providers.WeatherContract; +import java.util.UUID; + /** * This class holds the information of a request submitted to the active weather provider service */ @@ -36,7 +39,7 @@ public final class RequestInfo implements Parcelable { private int mRequestType; private IRequestInfoListener mListener; private int mTempUnit; - private int mKey; + private String mKey; private boolean mIsQueryOnly; /** @@ -155,6 +158,10 @@ public final class RequestInfo implements Parcelable { return this; } + /** + * Combine all of the options that have been set and return a new {@link RequestInfo} object + * @return {@link RequestInfo} + */ public RequestInfo build() { RequestInfo info = new RequestInfo(); info.mListener = this.mListener; @@ -164,7 +171,7 @@ public final class RequestInfo implements Parcelable { info.mLocation = this.mLocation; info.mTempUnit = this.mTempUnit; info.mIsQueryOnly = this.mIsQueryOnly; - info.mKey = this.hashCode(); + info.mKey = UUID.randomUUID().toString(); return info; } @@ -186,7 +193,7 @@ public final class RequestInfo implements Parcelable { int parcelableVersion = parcelInfo.getParcelVersion(); if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { - mKey = parcel.readInt(); + mKey = parcel.readString(); mRequestType = parcel.readInt(); switch (mRequestType) { case TYPE_WEATHER_BY_GEO_LOCATION_REQ: @@ -298,7 +305,7 @@ public final class RequestInfo implements Parcelable { ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== - dest.writeInt(mKey); + dest.writeString(mKey); dest.writeInt(mRequestType); switch (mRequestType) { case TYPE_WEATHER_BY_GEO_LOCATION_REQ: @@ -352,18 +359,19 @@ public final class RequestInfo implements Parcelable { @Override public int hashCode() { - //The hashcode of this object was stored when it was built. This is an - //immutable object but we need to preserve the hashcode since this object is parcelable and - //it's reconstructed over IPC, and clients of this object might want to store it in a - //collection that relies on this code to identify the object - return mKey; + final int prime = 31; + int result = 1; + result = prime * result + ((mKey != null) ? mKey.hashCode() : 0); + return result; } @Override public boolean equals(Object obj) { - if (obj instanceof RequestInfo) { + if (obj == null) return false; + + if (getClass() == obj.getClass()) { RequestInfo info = (RequestInfo) obj; - return (info.hashCode() == this.mKey); + return (TextUtils.equals(mKey, info.mKey)); } return false; } diff --git a/sdk/src/java/cyanogenmod/weather/WeatherInfo.java b/sdk/src/java/cyanogenmod/weather/WeatherInfo.java index 95fb2b7..aaac116 100755 --- a/sdk/src/java/cyanogenmod/weather/WeatherInfo.java +++ b/sdk/src/java/cyanogenmod/weather/WeatherInfo.java @@ -19,6 +19,7 @@ package cyanogenmod.weather; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import cyanogenmod.os.Build; import cyanogenmod.os.Concierge; import cyanogenmod.os.Concierge.ParcelInfo; @@ -27,6 +28,8 @@ import cyanogenmod.weatherservice.ServiceRequest; import cyanogenmod.weatherservice.ServiceRequestResult; import java.util.ArrayList; +import java.util.List; +import java.util.UUID; /** * This class represents the weather information that a @@ -51,8 +54,8 @@ public final class WeatherInfo implements Parcelable { private double mWindDirection; private int mWindSpeedUnit; private long mTimestamp; - private ArrayList mForecastList; - private int mKey; + private List mForecastList; + private String mKey; private WeatherInfo() {} @@ -71,7 +74,7 @@ public final class WeatherInfo implements Parcelable { private double mWindDirection = Double.NaN; private int mWindSpeedUnit = WeatherContract.WeatherColumns.WindSpeedUnit.MPH; private long mTimestamp = -1; - private ArrayList mForecastList = new ArrayList<>(0); + private List mForecastList = new ArrayList<>(0); /** * @param cityName A valid city name. Attempting to pass null will get you an @@ -169,7 +172,7 @@ public final class WeatherInfo implements Parcelable { * null will get you an IllegalArgumentException' * @return The {@link Builder} instance */ - public Builder setForecast(@NonNull ArrayList forecasts) { + public Builder setForecast(@NonNull List forecasts) { if (forecasts == null) { throw new IllegalArgumentException("Forecast list can't be null"); } @@ -220,7 +223,7 @@ public final class WeatherInfo implements Parcelable { info.mWindSpeedUnit = this.mWindSpeedUnit; info.mTimestamp = this.mTimestamp == -1 ? System.currentTimeMillis() : this.mTimestamp; info.mForecastList = this.mForecastList; - info.mKey = this.hashCode(); + info.mKey = UUID.randomUUID().toString(); return info; } @@ -338,7 +341,7 @@ public final class WeatherInfo implements Parcelable { * the forecast weather for the upcoming days. If you want to know today's high and low * temperatures, use {@link WeatherInfo#getTodaysHigh()} and {@link WeatherInfo#getTodaysLow()} */ - public ArrayList getForecasts() { + public List getForecasts() { return new ArrayList<>(mForecastList); } @@ -348,7 +351,7 @@ public final class WeatherInfo implements Parcelable { int parcelableVersion = parcelInfo.getParcelVersion(); if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { - mKey = parcel.readInt(); + mKey = parcel.readString(); mCity = parcel.readString(); mConditionCode = parcel.readInt(); mTemperature = parcel.readDouble(); @@ -383,7 +386,7 @@ public final class WeatherInfo implements Parcelable { ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== - dest.writeInt(mKey); + dest.writeString(mKey); dest.writeString(mCity); dest.writeInt(mConditionCode); dest.writeDouble(mTemperature); @@ -428,7 +431,7 @@ public final class WeatherInfo implements Parcelable { double mLow; double mHigh; int mConditionCode; - int mKey; + String mKey; private DayForecast() {} @@ -490,7 +493,7 @@ public final class WeatherInfo implements Parcelable { forecast.mLow = this.mLow; forecast.mHigh = this.mHigh; forecast.mConditionCode = this.mConditionCode; - forecast.mKey = this.hashCode(); + forecast.mKey = UUID.randomUUID().toString(); return forecast; } } @@ -527,7 +530,7 @@ public final class WeatherInfo implements Parcelable { ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== - dest.writeInt(mKey); + dest.writeString(mKey); dest.writeDouble(mLow); dest.writeDouble(mHigh); dest.writeInt(mConditionCode); @@ -555,7 +558,7 @@ public final class WeatherInfo implements Parcelable { int parcelableVersion = parcelInfo.getParcelVersion(); if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { - mKey = parcel.readInt(); + mKey = parcel.readString(); mLow = parcel.readDouble(); mHigh = parcel.readDouble(); mConditionCode = parcel.readInt(); @@ -576,18 +579,19 @@ public final class WeatherInfo implements Parcelable { @Override public int hashCode() { - //The hashcode of this object was stored when it was built. This is an - //immutable object but we need to preserve the hashcode since this object is parcelable - //and it's reconstructed over IPC, and clients of this object might want to store it in - //a collection that relies on this code to identify the object - return mKey; + final int prime = 31; + int result = 1; + result = prime * result + ((mKey != null) ? mKey.hashCode() : 0); + return result; } @Override public boolean equals(Object obj) { - if (obj instanceof DayForecast) { + if (obj == null) return false; + + if (getClass() == obj.getClass()) { DayForecast forecast = (DayForecast) obj; - return (forecast.hashCode() == this.mKey); + return (TextUtils.equals(mKey, forecast.mKey)); } return false; } @@ -615,18 +619,19 @@ public final class WeatherInfo implements Parcelable { @Override public int hashCode() { - //The hashcode of this object was stored when it was built. This is an - //immutable object but we need to preserve the hashcode since this object is parcelable and - //it's reconstructed over IPC, and clients of this object might want to store it in a - //collection that relies on this code to identify the object - return mKey; + final int prime = 31; + int result = 1; + result = prime * result + ((mKey != null) ? mKey.hashCode() : 0); + return result; } @Override public boolean equals(Object obj) { - if (obj instanceof WeatherInfo) { + if (obj == null) return false; + + if (getClass() == obj.getClass()) { WeatherInfo info = (WeatherInfo) obj; - return (info.hashCode() == this.mKey); + return (TextUtils.equals(mKey, info.mKey)); } return false; } diff --git a/sdk/src/java/cyanogenmod/weather/WeatherLocation.java b/sdk/src/java/cyanogenmod/weather/WeatherLocation.java index 6cc4741..6befbb4 100644 --- a/sdk/src/java/cyanogenmod/weather/WeatherLocation.java +++ b/sdk/src/java/cyanogenmod/weather/WeatherLocation.java @@ -24,6 +24,8 @@ import cyanogenmod.os.Build; import cyanogenmod.os.Concierge; import cyanogenmod.os.Concierge.ParcelInfo; +import java.util.UUID; + /** * A class representing a geographical location that a weather service provider can use to * get weather data from. Each service provider will potentially populate objects of this class @@ -37,7 +39,7 @@ public final class WeatherLocation implements Parcelable{ private String mPostal; private String mCountryId; private String mCountry; - private int mKey; + private String mKey; private WeatherLocation() {} @@ -57,24 +59,44 @@ public final class WeatherLocation implements Parcelable{ * @param cityName The name of the city */ public Builder(String cityId, String cityName) { - if (cityId == null && cityName == null) { + if (cityId == null || cityName == null) { throw new IllegalArgumentException("Illegal to set city id AND city to null"); } this.mCityId = cityId; this.mCity = cityName; } + /** + * @param cityName The name of the city + */ + public Builder(String cityName) { + if (cityName == null) { + throw new IllegalArgumentException("City name can't be null"); + } + this.mCity = cityName; + } + /** * @param countryId An identifier for the country (for example ISO alpha-2, ISO alpha-3, * ISO 3166-1 numeric-3, etc) + * @return The {@link Builder} instance + */ + public Builder setCountryId(String countryId) { + if (countryId == null) { + throw new IllegalArgumentException("Country ID can't be null"); + } + this.mCountryId = countryId; + return this; + } + + /** * @param country The country name * @return The {@link Builder} instance */ - public Builder setCountry(String countryId, String country) { - if (countryId == null && country == null) { - throw new IllegalArgumentException("Illegal to set country id AND country to null"); + public Builder setCountry(String country) { + if (country == null) { + throw new IllegalArgumentException("Country can't be null"); } - this.mCountryId = countryId; this.mCountry = country; return this; } @@ -116,48 +138,50 @@ public final class WeatherLocation implements Parcelable{ weatherLocation.mPostal = this.mPostal; weatherLocation.mCountryId = this.mCountryId; weatherLocation.mCountry = this.mCountry; - weatherLocation.mKey = this.hashCode(); + weatherLocation.mKey = UUID.randomUUID().toString(); return weatherLocation; } } /** - * @return The city ID + * @return The city ID. This method will return an empty string if the city ID was not set */ public String getCityId() { return mCityId; } /** - * @return The city name + * @return The city name. This method will return an empty string if the city name was not set */ public String getCity() { return mCity; } /** - * @return The state name + * @return The state name. This method will return an empty string if the state was not set */ public String getState() { return mState; } /** - * @return The postal/ZIP code + * @return The postal/ZIP code. This method will return an empty string if the postal/ZIP code + * was not set */ public String getPostalCode() { return mPostal; } /** - * @return The country ID + * @return The country ID. This method will return an empty string if the country ID was not set */ public String getCountryId() { return mCountryId; } /** - * @return The country name + * @return The country name. This method will return an empty string if the country ID was not + * set */ public String getCountry() { return mCountry; @@ -169,7 +193,7 @@ public final class WeatherLocation implements Parcelable{ int parcelableVersion = parcelInfo.getParcelVersion(); if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { - mKey = in.readInt(); + mKey = in.readString(); mCityId = in.readString(); mCity = in.readString(); mState = in.readString(); @@ -205,7 +229,7 @@ public final class WeatherLocation implements Parcelable{ ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== - dest.writeInt(mKey); + dest.writeString(mKey); dest.writeString(mCityId); dest.writeString(mCity); dest.writeString(mState); @@ -231,14 +255,19 @@ public final class WeatherLocation implements Parcelable{ @Override public int hashCode() { - return mKey; + final int prime = 31; + int result = 1; + result = prime * result + ((mKey != null) ? mKey.hashCode() : 0); + return result; } @Override public boolean equals(Object obj) { - if (obj instanceof WeatherLocation) { - WeatherLocation info = (WeatherLocation) obj; - return (info.hashCode() == this.mKey); + if (obj == null) return false; + + if (getClass() == obj.getClass()) { + WeatherLocation location = (WeatherLocation) obj; + return (TextUtils.equals(mKey, location.mKey)); } return false; } diff --git a/sdk/src/java/cyanogenmod/weatherservice/IWeatherProviderService.aidl b/sdk/src/java/cyanogenmod/weatherservice/IWeatherProviderService.aidl index 2a1deb5..c27f537 100644 --- a/sdk/src/java/cyanogenmod/weatherservice/IWeatherProviderService.aidl +++ b/sdk/src/java/cyanogenmod/weatherservice/IWeatherProviderService.aidl @@ -25,5 +25,5 @@ oneway interface IWeatherProviderService { void processCityNameLookupRequest(in RequestInfo request); void setServiceClient(in IWeatherProviderServiceClient client); void cancelOngoingRequests(); - void cancelRequest(in RequestInfo request); + void cancelRequest(int requestId); } \ No newline at end of file diff --git a/sdk/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java b/sdk/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java index 07f4cd9..753819b 100644 --- a/sdk/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java +++ b/sdk/src/java/cyanogenmod/weatherservice/ServiceRequestResult.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import cyanogenmod.os.Build; import cyanogenmod.os.Concierge; import cyanogenmod.os.Concierge.ParcelInfo; @@ -27,6 +28,8 @@ import cyanogenmod.weather.WeatherLocation; import cyanogenmod.weather.WeatherInfo; import java.util.ArrayList; +import java.util.List; +import java.util.UUID; /** * Use this class to build a request result. @@ -34,8 +37,8 @@ import java.util.ArrayList; public final class ServiceRequestResult implements Parcelable { private WeatherInfo mWeatherInfo; - private ArrayList mLocationLookupList; - private int mKey; + private List mLocationLookupList; + private String mKey; private ServiceRequestResult() {} @@ -45,7 +48,7 @@ public final class ServiceRequestResult implements Parcelable { int parcelableVersion = parcelInfo.getParcelVersion(); if (parcelableVersion >= Build.CM_VERSION_CODES.ELDERBERRY) { - mKey = in.readInt(); + mKey = in.readString(); int hasWeatherInfo = in.readInt(); if (hasWeatherInfo == 1) { mWeatherInfo = WeatherInfo.CREATOR.createFromParcel(in); @@ -89,7 +92,7 @@ public final class ServiceRequestResult implements Parcelable { ParcelInfo parcelInfo = Concierge.prepareParcel(dest); // ==== ELDERBERRY ===== - dest.writeInt(mKey); + dest.writeString(mKey); if (mWeatherInfo != null) { dest.writeInt(1); mWeatherInfo.writeToParcel(dest, 0); @@ -110,62 +113,49 @@ public final class ServiceRequestResult implements Parcelable { parcelInfo.complete(); } + /** + * Builder class for {@link ServiceRequestResult} + */ public static class Builder { - private WeatherInfo mBuilderWeatherInfo; - private ArrayList mBuilderLocationLookupList; + private WeatherInfo mWeatherInfo; + private List mLocationLookupList; public Builder() { - this.mBuilderWeatherInfo = null; - this.mBuilderLocationLookupList = null; + this.mWeatherInfo = null; + this.mLocationLookupList = null; } /** - * Add the supplied weather information to the result. Attempting to add a WeatherLocation - * list to the same builder will cause the system to throw IllegalArgumentException - * * @param weatherInfo The WeatherInfo object holding the data that will be used to update * the weather content provider */ - public Builder setWeatherInfo(@NonNull WeatherInfo weatherInfo) { - if (mBuilderLocationLookupList != null) { - throw new IllegalArgumentException("Can't add weather information when you have" - + " already added a WeatherLocation list"); - } - + public Builder(@NonNull WeatherInfo weatherInfo) { if (weatherInfo == null) { throw new IllegalArgumentException("WeatherInfo can't be null"); } - mBuilderWeatherInfo = weatherInfo; - return this; + mWeatherInfo = weatherInfo; } /** - * Add the supplied list of WeatherLocation objects to the result. Attempting to add a - * WeatherInfo object to the same builder will cause the system to throw - * IllegalArgumentException - * * @param locations The list of WeatherLocation objects. The list should not be null */ - public Builder setLocationLookupList(@NonNull ArrayList locations) { - if (mBuilderWeatherInfo != null) { - throw new IllegalArgumentException("Can't add a WeatherLocation list when you have" - + " already added weather information"); + public Builder(@NonNull List locations) { + if (locations == null) { + throw new IllegalArgumentException("Weather location list can't be null"); } - - mBuilderLocationLookupList = locations; - return this; + mLocationLookupList = locations; } /** - * Creates a {@link ServiceRequest} with the arguments + * Creates a {@link ServiceRequestResult} with the arguments * supplied to this builder * @return {@link ServiceRequestResult} */ public ServiceRequestResult build() { ServiceRequestResult result = new ServiceRequestResult(); - result.mWeatherInfo = this.mBuilderWeatherInfo; - result.mLocationLookupList = this.mBuilderLocationLookupList; - result.mKey = this.hashCode(); + result.mWeatherInfo = this.mWeatherInfo; + result.mLocationLookupList = this.mLocationLookupList; + result.mKey = UUID.randomUUID().toString(); return result; } } @@ -180,24 +170,25 @@ public final class ServiceRequestResult implements Parcelable { /** * @return The list of WeatherLocation objects supplied by the weather provider service */ - public ArrayList getLocationLookupList() { - return mLocationLookupList; + public List getLocationLookupList() { + return new ArrayList<>(mLocationLookupList); } @Override public int hashCode() { - //The hashcode of this object was stored when it was built. This is an - //immutable object but we need to preserve the hashcode since this object is parcelable and - //it's reconstructed over IPC, and clients of this object might want to store it in a - //collection that relies on this code to identify the object - return mKey; + final int prime = 31; + int result = 1; + result = prime * result + ((mKey != null) ? mKey.hashCode() : 0); + return result; } @Override public boolean equals(Object obj) { - if (obj instanceof ServiceRequestResult) { + if (obj == null) return false; + + if (getClass() == obj.getClass()) { ServiceRequestResult request = (ServiceRequestResult) obj; - return (request.hashCode() == this.mKey); + return (TextUtils.equals(mKey, request.mKey)); } return false; } diff --git a/sdk/src/java/cyanogenmod/weatherservice/WeatherProviderService.java b/sdk/src/java/cyanogenmod/weatherservice/WeatherProviderService.java index 8a1f30c..d090ae5 100644 --- a/sdk/src/java/cyanogenmod/weatherservice/WeatherProviderService.java +++ b/sdk/src/java/cyanogenmod/weatherservice/WeatherProviderService.java @@ -108,13 +108,29 @@ public abstract class WeatherProviderService extends Service { @Override public void cancelOngoingRequests() { - mHandler.obtainMessage(ServiceHandler.MSG_CANCEL_ALL_OUTSTANDING_REQUESTS) - .sendToTarget(); + synchronized (mWeakRequestsSet) { + for (final ServiceRequest request : mWeakRequestsSet) { + request.cancel(); + mWeakRequestsSet.remove(request); + mHandler.obtainMessage(ServiceHandler.MSG_CANCEL_REQUEST, request) + .sendToTarget(); + } + } } @Override - public void cancelRequest(RequestInfo info) { - mHandler.obtainMessage(ServiceHandler.MSG_CANCEL_REQUEST, info).sendToTarget(); + public void cancelRequest(int requestId) { + synchronized (mWeakRequestsSet) { + for (final ServiceRequest request : mWeakRequestsSet) { + if (request.getRequestInfo().hashCode() == requestId) { + mWeakRequestsSet.remove(request); + request.cancel(); + mHandler.obtainMessage(ServiceHandler.MSG_CANCEL_REQUEST, request) + .sendToTarget(); + break; + } + } + } } }; @@ -125,8 +141,7 @@ public abstract class WeatherProviderService extends Service { } public static final int MSG_SET_CLIENT = 1; public static final int MSG_ON_NEW_REQUEST = 2; - public static final int MSG_CANCEL_ALL_OUTSTANDING_REQUESTS = 3; - public static final int MSG_CANCEL_REQUEST = 4; + public static final int MSG_CANCEL_REQUEST = 3; @Override public void handleMessage(Message msg) { @@ -151,41 +166,9 @@ public abstract class WeatherProviderService extends Service { } return; } - case MSG_CANCEL_ALL_OUTSTANDING_REQUESTS: { - synchronized (mWeakRequestsSet) { - for (final ServiceRequest request : mWeakRequestsSet) { - if (request != null) { - request.cancel(); - mWeakRequestsSet.remove(request); - mHandler.post(new Runnable() { - @Override - public void run() { - onRequestCancelled(request); - } - }); - } - } - } - return; - } case MSG_CANCEL_REQUEST: { - synchronized (mWeakRequestsSet) { - RequestInfo info = (RequestInfo) msg.obj; - if (info == null) return; - for (final ServiceRequest request : mWeakRequestsSet) { - if (request.getRequestInfo().equals(info)) { - request.cancel(); - mWeakRequestsSet.remove(request); - mHandler.post(new Runnable() { - @Override - public void run() { - onRequestCancelled(request); - } - }); - break; - } - } - } + ServiceRequest request = (ServiceRequest) msg.obj; + onRequestCancelled(request); return; } } diff --git a/system-api/cm_system-current.txt b/system-api/cm_system-current.txt index 5992f3f..f3b5536 100644 --- a/system-api/cm_system-current.txt +++ b/system-api/cm_system-current.txt @@ -1351,13 +1351,13 @@ package cyanogenmod.util { package cyanogenmod.weather { public class CMWeatherManager { - method public void cancelRequest(cyanogenmod.weather.RequestInfo); + method public void cancelRequest(int); method public java.lang.String getActiveWeatherServiceProviderLabel(); method public static cyanogenmod.weather.CMWeatherManager getInstance(android.content.Context); - method public cyanogenmod.weather.RequestInfo lookupCity(java.lang.String, cyanogenmod.weather.CMWeatherManager.LookupCityRequestListener); + method public int lookupCity(java.lang.String, cyanogenmod.weather.CMWeatherManager.LookupCityRequestListener); method public void registerWeatherServiceProviderChangeListener(cyanogenmod.weather.CMWeatherManager.WeatherServiceProviderChangeListener); - method public cyanogenmod.weather.RequestInfo requestWeatherUpdate(android.location.Location, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); - method public cyanogenmod.weather.RequestInfo requestWeatherUpdate(cyanogenmod.weather.WeatherLocation, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); + method public int requestWeatherUpdate(android.location.Location, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); + method public int requestWeatherUpdate(cyanogenmod.weather.WeatherLocation, cyanogenmod.weather.CMWeatherManager.WeatherUpdateRequestListener); method public void unregisterWeatherServiceProviderChangeListener(cyanogenmod.weather.CMWeatherManager.WeatherServiceProviderChangeListener); field public static final int WEATHER_REQUEST_ALREADY_IN_PROGRESS = -3; // 0xfffffffd field public static final int WEATHER_REQUEST_COMPLETED = 1; // 0x1 @@ -1366,7 +1366,7 @@ package cyanogenmod.weather { } public static abstract interface CMWeatherManager.LookupCityRequestListener { - method public abstract void onLookupCityRequestCompleted(java.util.ArrayList); + method public abstract void onLookupCityRequestCompleted(java.util.List); } public static abstract interface CMWeatherManager.WeatherServiceProviderChangeListener { @@ -1395,7 +1395,7 @@ package cyanogenmod.weather { method public int describeContents(); method public java.lang.String getCity(); method public int getConditionCode(); - method public java.util.ArrayList getForecasts(); + method public java.util.List getForecasts(); method public double getHumidity(); method public double getTemperature(); method public int getTemperatureUnit(); @@ -1412,7 +1412,7 @@ package cyanogenmod.weather { public static class WeatherInfo.Builder { ctor public WeatherInfo.Builder(java.lang.String, double, int); method public cyanogenmod.weather.WeatherInfo build(); - method public cyanogenmod.weather.WeatherInfo.Builder setForecast(java.util.ArrayList); + method public cyanogenmod.weather.WeatherInfo.Builder setForecast(java.util.List); method public cyanogenmod.weather.WeatherInfo.Builder setHumidity(double); method public cyanogenmod.weather.WeatherInfo.Builder setTimestamp(long); method public cyanogenmod.weather.WeatherInfo.Builder setTodaysHigh(double); @@ -1451,8 +1451,10 @@ package cyanogenmod.weather { public static class WeatherLocation.Builder { ctor public WeatherLocation.Builder(java.lang.String, java.lang.String); + ctor public WeatherLocation.Builder(java.lang.String); method public cyanogenmod.weather.WeatherLocation build(); - method public cyanogenmod.weather.WeatherLocation.Builder setCountry(java.lang.String, java.lang.String); + method public cyanogenmod.weather.WeatherLocation.Builder setCountry(java.lang.String); + method public cyanogenmod.weather.WeatherLocation.Builder setCountryId(java.lang.String); method public cyanogenmod.weather.WeatherLocation.Builder setPostalCode(java.lang.String); method public cyanogenmod.weather.WeatherLocation.Builder setState(java.lang.String); } @@ -1469,7 +1471,7 @@ package cyanogenmod.weatherservice { public final class ServiceRequestResult implements android.os.Parcelable { method public int describeContents(); - method public java.util.ArrayList getLocationLookupList(); + method public java.util.List getLocationLookupList(); method public cyanogenmod.weather.WeatherInfo getWeatherInfo(); method public void writeToParcel(android.os.Parcel, int); field public static final android.os.Parcelable.Creator CREATOR; @@ -1477,9 +1479,9 @@ package cyanogenmod.weatherservice { public static class ServiceRequestResult.Builder { ctor public ServiceRequestResult.Builder(); + ctor public ServiceRequestResult.Builder(cyanogenmod.weather.WeatherInfo); + ctor public ServiceRequestResult.Builder(java.util.List); method public cyanogenmod.weatherservice.ServiceRequestResult build(); - method public cyanogenmod.weatherservice.ServiceRequestResult.Builder setLocationLookupList(java.util.ArrayList); - method public cyanogenmod.weatherservice.ServiceRequestResult.Builder setWeatherInfo(cyanogenmod.weather.WeatherInfo); } public abstract class WeatherProviderService extends android.app.Service {