content: /*
   * Copyright (C) 2016 The Android Open Source 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 android.telephony.mbms;
  
  import android.annotation.NonNull;
  import android.annotation.Nullable;
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.text.TextUtils;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Locale;
  import java.util.Map;
  import java.util.NoSuchElementException;
  import java.util.Objects;
  import java.util.Set;
  
  /**
   * Describes a cell-broadcast service. This class should not be instantiated directly -- use
   * {@link StreamingServiceInfo} or {@link FileServiceInfo}
   */
  public class ServiceInfo {
      // arbitrary limit on the number of locale -> name pairs we support
      final static int MAP_LIMIT = 1000;
  
      private final Map<Locale, String> names;
      private final String className;
      private final List<Locale> locales;
      private final String serviceId;
      private final Date sessionStartTime;
      private final Date sessionEndTime;
  
      /** @hide */
      public ServiceInfo(Map<Locale, String> newNames, String newClassName, List<Locale> newLocales,
              String newServiceId, Date start, Date end) {
          if (newNames == null || newClassName == null
                  || newLocales == null || newServiceId == null
                  || start == null || end == null) {
              throw new IllegalArgumentException("Bad ServiceInfo construction");
          }
          if (newNames.size() > MAP_LIMIT) {
              throw new RuntimeException("bad map length " + newNames.size());
          }
          if (newLocales.size() > MAP_LIMIT) {
              throw new RuntimeException("bad locales length " + newLocales.size());
          }
  
          names = new HashMap(newNames.size());
          names.putAll(newNames);
          className = newClassName;
          locales = new ArrayList(newLocales);
          serviceId = newServiceId;
          sessionStartTime = (Date)start.clone();
          sessionEndTime = (Date)end.clone();
      }
  
      /** @hide */
      protected ServiceInfo(Parcel in) {
          int mapCount = in.readInt();
          if (mapCount > MAP_LIMIT || mapCount < 0) {
              throw new RuntimeException("bad map length" + mapCount);
          }
          names = new HashMap(mapCount);
          while (mapCount-- > 0) {
              Locale locale = (java.util.Locale) in.readSerializable();
              String name = in.readString();
              names.put(locale, name);
          }
          className = in.readString();
          int localesCount = in.readInt();
          if (localesCount > MAP_LIMIT || localesCount < 0) {
              throw new RuntimeException("bad locale length " + localesCount);
          }
          locales = new ArrayList<Locale>(localesCount);
          while (localesCount-- > 0) {
              Locale l = (java.util.Locale) in.readSerializable();
              locales.add(l);
          }
          serviceId = in.readString();
          sessionStartTime = (java.util.Date) in.readSerializable();
          sessionEndTime = (java.util.Date) in.readSerializable();
      }
  
      /** @hide */
      public void writeToParcel(Parcel dest, int flags) {
          Set<Locale> keySet = names.keySet();
          dest.writeInt(keySet.size());
          for (Locale l : keySet) {
              dest.writeSerializable(l);
              dest.writeString(names.get(l));
          }
          dest.writeString(className);
          int localesCount = locales.size();
          dest.writeInt(localesCount);
          for (Locale l : locales) {
              dest.writeSerializable(l);
          }
          dest.writeString(serviceId);
          dest.writeSerializable(sessionStartTime);
          dest.writeSerializable(sessionEndTime);
      }
  
      /**
       * Get the user-displayable name for this cell-broadcast service corresponding to the
       * provided {@link Locale}.
       * @param locale The {@link Locale} in which you want the name of the service. This must be a
       *               value from the set returned by {@link #getNamedContentLocales()} -- an
       *               {@link java.util.NoSuchElementException} may be thrown otherwise.
       * @return The {@link CharSequence} providing the name of the service in the given
       *         {@link Locale}
       */
      public @NonNull CharSequence getNameForLocale(@NonNull Locale locale) {
          if (!names.containsKey(locale)) {
              throw new NoSuchElementException("Locale not supported");
          }
          return names.get(locale);
      }
  
      /**
       * Return an unmodifiable set of the current {@link Locale}s that have a user-displayable name
       * associated with them. The user-displayable name associated with any {@link Locale} in this
       * set can be retrieved with {@link #getNameForLocale(Locale)}.
       * @return An unmodifiable set of {@link Locale} objects corresponding to a user-displayable
       * content name in that locale.
       */
      public @NonNull Set<Locale> getNamedContentLocales() {
          return Collections.unmodifiableSet(names.keySet());
      }
  
      /**
       * The class name for this service - used to categorize and filter
       */
      public String getServiceClassName() {
          return className;
      }
  
      /**
       * The languages available for this service content
       */
      public List<Locale> getLocales() {
          return locales;
      }
  
      /**
       * The carrier's identifier for the service.
       */
      public String getServiceId() {
          return serviceId;
      }
  
      /**
       * The start time indicating when this service will be available.
       */
      public Date getSessionStartTime() {
          return sessionStartTime;
      }
  
      /**
       * The end time indicating when this session stops being available.
       */
      public Date getSessionEndTime() {
          return sessionEndTime;
      }
  
      @Override
      public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null) {
              return false;
          }
          if (!(o instanceof ServiceInfo)) {
              return false;
          }
          ServiceInfo that = (ServiceInfo) o;
          return Objects.equals(names, that.names) &&
                  Objects.equals(className, that.className) &&
                  Objects.equals(locales, that.locales) &&
                  Objects.equals(serviceId, that.serviceId) &&
                  Objects.equals(sessionStartTime, that.sessionStartTime) &&
                  Objects.equals(sessionEndTime, that.sessionEndTime);
      }
  
      @Override
      public int hashCode() {
          return Objects.hash(names, className, locales, serviceId, sessionStartTime, sessionEndTime);
      }
  }
  