Home | History | Annotate | Download | only in common
      1 /*
      2  * Copyright 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 package com.android.managedprovisioning.common;
     17 
     18 import android.os.Parcel;
     19 import android.os.Parcelable;
     20 import android.os.PersistableBundle;
     21 import android.support.annotation.NonNull;
     22 import android.text.TextUtils;
     23 import java.util.ArrayList;
     24 import java.util.Arrays;
     25 import java.util.Collections;
     26 import java.util.List;
     27 import java.util.Objects;
     28 import java.util.Set;
     29 
     30 public abstract class PersistableBundlable implements Parcelable {
     31     public abstract @NonNull PersistableBundle toPersistableBundle();
     32 
     33     public static PersistableBundle getPersistableBundleFromParcel(Parcel parcel) {
     34         return parcel.readParcelable(PersistableBundle.class.getClassLoader());
     35     }
     36 
     37     @Override
     38     public boolean equals(Object object) {
     39         return isPersistableBundlableEquals(this, object);
     40     }
     41 
     42     @Override
     43     public int hashCode() {
     44         // Concatenated sorted keys should be good enough as a hash
     45         List<String> keys = new ArrayList(toPersistableBundle().keySet());
     46         Collections.sort(keys);
     47         return TextUtils.join(",", keys).hashCode();
     48     }
     49 
     50     @Override
     51     public int describeContents() {
     52         return 0;
     53     }
     54 
     55     @Override
     56     public void writeToParcel(Parcel dest, int flags) {
     57         dest.writeParcelable(toPersistableBundle(), flags);
     58     }
     59 
     60     private static boolean isPersistableBundlableEquals(PersistableBundlable pb1, Object obj) {
     61         if (pb1 == obj) {
     62             return true;
     63         }
     64         if (obj == null || pb1.getClass() != obj.getClass()) {
     65             return false;
     66         }
     67 
     68         // obj has to be PersistableBundlable as it has the same class
     69         PersistableBundlable pb2 = (PersistableBundlable) obj;
     70         return isPersistableBundleEquals(pb1.toPersistableBundle(), pb2.toPersistableBundle());
     71     }
     72 
     73     /**
     74      * Compares two {@link PersistableBundle} objects are equals.
     75      */
     76     private static boolean isPersistableBundleEquals(PersistableBundle obj1, PersistableBundle obj2) {
     77         if (obj1 == obj2) {
     78             return true;
     79         }
     80         if (obj1 == null || obj2 == null || obj1.size() != obj2.size()) {
     81             return false;
     82         }
     83         Set<String> keys = obj1.keySet();
     84         for (String key : keys) {
     85             Object val1 = obj1.get(key);
     86             Object val2 = obj2.get(key);
     87             if (!isPersistableBundleSupportedValueEquals(val1, val2)) {
     88                 return false;
     89             }
     90         }
     91         return true;
     92     }
     93 
     94     /**
     95      * Compares two values which type is supported by {@link PersistableBundle}.
     96      *
     97      * <p>If the type isn't supported. The equality is done by {@link Object#equals(Object)}.
     98      */
     99     private static boolean isPersistableBundleSupportedValueEquals(Object val1, Object val2) {
    100         if (val1 == val2) {
    101             return true;
    102         } else if (val1 == null || val2 == null || !val1.getClass().equals(val2.getClass())) {
    103             return false;
    104         } else if (val1 instanceof PersistableBundle) {
    105             return isPersistableBundleEquals((PersistableBundle) val1, (PersistableBundle) val2);
    106         } else if (val1 instanceof int[]) {
    107             return Arrays.equals((int[]) val1, (int[]) val2);
    108         } else if (val1 instanceof long[]) {
    109             return Arrays.equals((long[]) val1, (long[]) val2);
    110         } else if (val1 instanceof double[]) {
    111             return Arrays.equals((double[]) val1, (double[]) val2);
    112         } else if (val1 instanceof boolean[]) {
    113             return Arrays.equals((boolean[]) val1, (boolean[]) val2);
    114         } else if (val1 instanceof String[]) {
    115             return Arrays.equals((String[]) val1, (String[]) val2);
    116         } else {
    117             return Objects.equals(val1, val2);
    118         }
    119     }
    120 
    121 }
    122