1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.telephony.mbms;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.os.Parcel;
22import android.os.Parcelable;
23import android.text.TextUtils;
24
25import java.util.ArrayList;
26import java.util.Collections;
27import java.util.Date;
28import java.util.HashMap;
29import java.util.List;
30import java.util.Locale;
31import java.util.Map;
32import java.util.NoSuchElementException;
33import java.util.Objects;
34import java.util.Set;
35
36/**
37 * Describes a cell-broadcast service. This class should not be instantiated directly -- use
38 * {@link StreamingServiceInfo} or {@link FileServiceInfo}
39 */
40public class ServiceInfo {
41    // arbitrary limit on the number of locale -> name pairs we support
42    final static int MAP_LIMIT = 1000;
43
44    private final Map<Locale, String> names;
45    private final String className;
46    private final List<Locale> locales;
47    private final String serviceId;
48    private final Date sessionStartTime;
49    private final Date sessionEndTime;
50
51    /** @hide */
52    public ServiceInfo(Map<Locale, String> newNames, String newClassName, List<Locale> newLocales,
53            String newServiceId, Date start, Date end) {
54        if (newNames == null || newClassName == null
55                || newLocales == null || newServiceId == null
56                || start == null || end == null) {
57            throw new IllegalArgumentException("Bad ServiceInfo construction");
58        }
59        if (newNames.size() > MAP_LIMIT) {
60            throw new RuntimeException("bad map length " + newNames.size());
61        }
62        if (newLocales.size() > MAP_LIMIT) {
63            throw new RuntimeException("bad locales length " + newLocales.size());
64        }
65
66        names = new HashMap(newNames.size());
67        names.putAll(newNames);
68        className = newClassName;
69        locales = new ArrayList(newLocales);
70        serviceId = newServiceId;
71        sessionStartTime = (Date)start.clone();
72        sessionEndTime = (Date)end.clone();
73    }
74
75    /** @hide */
76    protected ServiceInfo(Parcel in) {
77        int mapCount = in.readInt();
78        if (mapCount > MAP_LIMIT || mapCount < 0) {
79            throw new RuntimeException("bad map length" + mapCount);
80        }
81        names = new HashMap(mapCount);
82        while (mapCount-- > 0) {
83            Locale locale = (java.util.Locale) in.readSerializable();
84            String name = in.readString();
85            names.put(locale, name);
86        }
87        className = in.readString();
88        int localesCount = in.readInt();
89        if (localesCount > MAP_LIMIT || localesCount < 0) {
90            throw new RuntimeException("bad locale length " + localesCount);
91        }
92        locales = new ArrayList<Locale>(localesCount);
93        while (localesCount-- > 0) {
94            Locale l = (java.util.Locale) in.readSerializable();
95            locales.add(l);
96        }
97        serviceId = in.readString();
98        sessionStartTime = (java.util.Date) in.readSerializable();
99        sessionEndTime = (java.util.Date) in.readSerializable();
100    }
101
102    /** @hide */
103    public void writeToParcel(Parcel dest, int flags) {
104        Set<Locale> keySet = names.keySet();
105        dest.writeInt(keySet.size());
106        for (Locale l : keySet) {
107            dest.writeSerializable(l);
108            dest.writeString(names.get(l));
109        }
110        dest.writeString(className);
111        int localesCount = locales.size();
112        dest.writeInt(localesCount);
113        for (Locale l : locales) {
114            dest.writeSerializable(l);
115        }
116        dest.writeString(serviceId);
117        dest.writeSerializable(sessionStartTime);
118        dest.writeSerializable(sessionEndTime);
119    }
120
121    /**
122     * Get the user-displayable name for this cell-broadcast service corresponding to the
123     * provided {@link Locale}.
124     * @param locale The {@link Locale} in which you want the name of the service. This must be a
125     *               value from the set returned by {@link #getNamedContentLocales()} -- an
126     *               {@link java.util.NoSuchElementException} may be thrown otherwise.
127     * @return The {@link CharSequence} providing the name of the service in the given
128     *         {@link Locale}
129     */
130    public @NonNull CharSequence getNameForLocale(@NonNull Locale locale) {
131        if (!names.containsKey(locale)) {
132            throw new NoSuchElementException("Locale not supported");
133        }
134        return names.get(locale);
135    }
136
137    /**
138     * Return an unmodifiable set of the current {@link Locale}s that have a user-displayable name
139     * associated with them. The user-displayable name associated with any {@link Locale} in this
140     * set can be retrieved with {@link #getNameForLocale(Locale)}.
141     * @return An unmodifiable set of {@link Locale} objects corresponding to a user-displayable
142     * content name in that locale.
143     */
144    public @NonNull Set<Locale> getNamedContentLocales() {
145        return Collections.unmodifiableSet(names.keySet());
146    }
147
148    /**
149     * The class name for this service - used to categorize and filter
150     */
151    public String getServiceClassName() {
152        return className;
153    }
154
155    /**
156     * The languages available for this service content
157     */
158    public List<Locale> getLocales() {
159        return locales;
160    }
161
162    /**
163     * The carrier's identifier for the service.
164     */
165    public String getServiceId() {
166        return serviceId;
167    }
168
169    /**
170     * The start time indicating when this service will be available.
171     */
172    public Date getSessionStartTime() {
173        return sessionStartTime;
174    }
175
176    /**
177     * The end time indicating when this session stops being available.
178     */
179    public Date getSessionEndTime() {
180        return sessionEndTime;
181    }
182
183    @Override
184    public boolean equals(Object o) {
185        if (this == o) return true;
186        if (o == null) {
187            return false;
188        }
189        if (!(o instanceof ServiceInfo)) {
190            return false;
191        }
192        ServiceInfo that = (ServiceInfo) o;
193        return Objects.equals(names, that.names) &&
194                Objects.equals(className, that.className) &&
195                Objects.equals(locales, that.locales) &&
196                Objects.equals(serviceId, that.serviceId) &&
197                Objects.equals(sessionStartTime, that.sessionStartTime) &&
198                Objects.equals(sessionEndTime, that.sessionEndTime);
199    }
200
201    @Override
202    public int hashCode() {
203        return Objects.hash(names, className, locales, serviceId, sessionStartTime, sessionEndTime);
204    }
205}
206