16a35dc83f18572097134c4864360743f02d4cd99Victor Chang/*
26a35dc83f18572097134c4864360743f02d4cd99Victor Chang * Copyright 2016, The Android Open Source Project
36a35dc83f18572097134c4864360743f02d4cd99Victor Chang *
46a35dc83f18572097134c4864360743f02d4cd99Victor Chang * Licensed under the Apache License, Version 2.0 (the "License");
56a35dc83f18572097134c4864360743f02d4cd99Victor Chang * you may not use this file except in compliance with the License.
66a35dc83f18572097134c4864360743f02d4cd99Victor Chang * You may obtain a copy of the License at
76a35dc83f18572097134c4864360743f02d4cd99Victor Chang *
86a35dc83f18572097134c4864360743f02d4cd99Victor Chang *     http://www.apache.org/licenses/LICENSE-2.0
96a35dc83f18572097134c4864360743f02d4cd99Victor Chang *
106a35dc83f18572097134c4864360743f02d4cd99Victor Chang * Unless required by applicable law or agreed to in writing, software
116a35dc83f18572097134c4864360743f02d4cd99Victor Chang * distributed under the License is distributed on an "AS IS" BASIS,
126a35dc83f18572097134c4864360743f02d4cd99Victor Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136a35dc83f18572097134c4864360743f02d4cd99Victor Chang * See the License for the specific language governing permissions and
146a35dc83f18572097134c4864360743f02d4cd99Victor Chang * limitations under the License.
156a35dc83f18572097134c4864360743f02d4cd99Victor Chang */
166a35dc83f18572097134c4864360743f02d4cd99Victor Changpackage com.android.managedprovisioning.common;
176a35dc83f18572097134c4864360743f02d4cd99Victor Chang
186a35dc83f18572097134c4864360743f02d4cd99Victor Changimport android.os.Parcel;
196a35dc83f18572097134c4864360743f02d4cd99Victor Changimport android.os.Parcelable;
206a35dc83f18572097134c4864360743f02d4cd99Victor Changimport android.os.PersistableBundle;
2190f58ca887207a527c80d7e9ccea97e205c960d4Victor Changimport android.support.annotation.NonNull;
22a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Changimport android.text.TextUtils;
23a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Changimport java.util.ArrayList;
246a35dc83f18572097134c4864360743f02d4cd99Victor Changimport java.util.Arrays;
25a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Changimport java.util.Collections;
26a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Changimport java.util.List;
276a35dc83f18572097134c4864360743f02d4cd99Victor Changimport java.util.Objects;
286a35dc83f18572097134c4864360743f02d4cd99Victor Changimport java.util.Set;
296a35dc83f18572097134c4864360743f02d4cd99Victor Chang
30a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Changpublic abstract class PersistableBundlable implements Parcelable {
31a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    public abstract @NonNull PersistableBundle toPersistableBundle();
326a35dc83f18572097134c4864360743f02d4cd99Victor Chang
33a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    public static PersistableBundle getPersistableBundleFromParcel(Parcel parcel) {
346a35dc83f18572097134c4864360743f02d4cd99Victor Chang        return parcel.readParcelable(PersistableBundle.class.getClassLoader());
356a35dc83f18572097134c4864360743f02d4cd99Victor Chang    }
366a35dc83f18572097134c4864360743f02d4cd99Victor Chang
37a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    @Override
38a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    public boolean equals(Object object) {
39a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang        return isPersistableBundlableEquals(this, object);
40a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    }
41a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang
42a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    @Override
43a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    public int hashCode() {
44a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang        // Concatenated sorted keys should be good enough as a hash
45a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang        List<String> keys = new ArrayList(toPersistableBundle().keySet());
46059f6c435c561226b1e8c629396b55302aec3772Victor Chang        Collections.sort(keys);
47a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang        return TextUtils.join(",", keys).hashCode();
48a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    }
49a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang
50a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    @Override
51a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    public int describeContents() {
52a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang        return 0;
53a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    }
54a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang
55a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    @Override
56a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    public void writeToParcel(Parcel dest, int flags) {
57a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang        dest.writeParcelable(toPersistableBundle(), flags);
58a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    }
59a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang
60a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    private static boolean isPersistableBundlableEquals(PersistableBundlable pb1, Object obj) {
616a35dc83f18572097134c4864360743f02d4cd99Victor Chang        if (pb1 == obj) {
626a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return true;
636a35dc83f18572097134c4864360743f02d4cd99Victor Chang        }
646a35dc83f18572097134c4864360743f02d4cd99Victor Chang        if (obj == null || pb1.getClass() != obj.getClass()) {
656a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return false;
666a35dc83f18572097134c4864360743f02d4cd99Victor Chang        }
676a35dc83f18572097134c4864360743f02d4cd99Victor Chang
686a35dc83f18572097134c4864360743f02d4cd99Victor Chang        // obj has to be PersistableBundlable as it has the same class
696a35dc83f18572097134c4864360743f02d4cd99Victor Chang        PersistableBundlable pb2 = (PersistableBundlable) obj;
706a35dc83f18572097134c4864360743f02d4cd99Victor Chang        return isPersistableBundleEquals(pb1.toPersistableBundle(), pb2.toPersistableBundle());
716a35dc83f18572097134c4864360743f02d4cd99Victor Chang    }
726a35dc83f18572097134c4864360743f02d4cd99Victor Chang
736a35dc83f18572097134c4864360743f02d4cd99Victor Chang    /**
746a35dc83f18572097134c4864360743f02d4cd99Victor Chang     * Compares two {@link PersistableBundle} objects are equals.
756a35dc83f18572097134c4864360743f02d4cd99Victor Chang     */
76a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    private static boolean isPersistableBundleEquals(PersistableBundle obj1, PersistableBundle obj2) {
776a35dc83f18572097134c4864360743f02d4cd99Victor Chang        if (obj1 == obj2) {
786a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return true;
796a35dc83f18572097134c4864360743f02d4cd99Victor Chang        }
806a35dc83f18572097134c4864360743f02d4cd99Victor Chang        if (obj1 == null || obj2 == null || obj1.size() != obj2.size()) {
816a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return false;
826a35dc83f18572097134c4864360743f02d4cd99Victor Chang        }
836a35dc83f18572097134c4864360743f02d4cd99Victor Chang        Set<String> keys = obj1.keySet();
846a35dc83f18572097134c4864360743f02d4cd99Victor Chang        for (String key : keys) {
856a35dc83f18572097134c4864360743f02d4cd99Victor Chang            Object val1 = obj1.get(key);
866a35dc83f18572097134c4864360743f02d4cd99Victor Chang            Object val2 = obj2.get(key);
876a35dc83f18572097134c4864360743f02d4cd99Victor Chang            if (!isPersistableBundleSupportedValueEquals(val1, val2)) {
886a35dc83f18572097134c4864360743f02d4cd99Victor Chang                return false;
896a35dc83f18572097134c4864360743f02d4cd99Victor Chang            }
906a35dc83f18572097134c4864360743f02d4cd99Victor Chang        }
916a35dc83f18572097134c4864360743f02d4cd99Victor Chang        return true;
926a35dc83f18572097134c4864360743f02d4cd99Victor Chang    }
936a35dc83f18572097134c4864360743f02d4cd99Victor Chang
946a35dc83f18572097134c4864360743f02d4cd99Victor Chang    /**
956a35dc83f18572097134c4864360743f02d4cd99Victor Chang     * Compares two values which type is supported by {@link PersistableBundle}.
966a35dc83f18572097134c4864360743f02d4cd99Victor Chang     *
976a35dc83f18572097134c4864360743f02d4cd99Victor Chang     * <p>If the type isn't supported. The equality is done by {@link Object#equals(Object)}.
986a35dc83f18572097134c4864360743f02d4cd99Victor Chang     */
99a6283e0106a8c3af0d5ed33bbb7a86d1b3661f81Victor Chang    private static boolean isPersistableBundleSupportedValueEquals(Object val1, Object val2) {
1006a35dc83f18572097134c4864360743f02d4cd99Victor Chang        if (val1 == val2) {
1016a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return true;
1026a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else if (val1 == null || val2 == null || !val1.getClass().equals(val2.getClass())) {
1036a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return false;
1046a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else if (val1 instanceof PersistableBundle) {
1056a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return isPersistableBundleEquals((PersistableBundle) val1, (PersistableBundle) val2);
1066a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else if (val1 instanceof int[]) {
1076a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return Arrays.equals((int[]) val1, (int[]) val2);
1086a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else if (val1 instanceof long[]) {
1096a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return Arrays.equals((long[]) val1, (long[]) val2);
1106a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else if (val1 instanceof double[]) {
1116a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return Arrays.equals((double[]) val1, (double[]) val2);
1126a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else if (val1 instanceof boolean[]) {
1136a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return Arrays.equals((boolean[]) val1, (boolean[]) val2);
1146a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else if (val1 instanceof String[]) {
1156a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return Arrays.equals((String[]) val1, (String[]) val2);
1166a35dc83f18572097134c4864360743f02d4cd99Victor Chang        } else {
1176a35dc83f18572097134c4864360743f02d4cd99Victor Chang            return Objects.equals(val1, val2);
1186a35dc83f18572097134c4864360743f02d4cd99Victor Chang        }
1196a35dc83f18572097134c4864360743f02d4cd99Victor Chang    }
1206a35dc83f18572097134c4864360743f02d4cd99Victor Chang
1216a35dc83f18572097134c4864360743f02d4cd99Victor Chang}
122