1 /*
2  * Copyright (C) 2020 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 
17 package com.android.server.utils;
18 
19 import android.annotation.NonNull;
20 import android.util.SparseArray;
21 import android.util.SparseIntArray;
22 import android.util.SparseSetArray;
23 
24 /**
25  * A collection of useful methods for manipulating Snapshot classes.  This is similar to
26  * java.util.Objects or java.util.Arrays.
27  */
28 public class Snapshots {
29 
30     /**
31      * Return the snapshot of an object, if the object extends {@link Snapper}, or the object
32      * itself.
33      * @param o The object to be copied
34      * @return A snapshot of the object, if the object extends {@link Snapper}
35      */
maybeSnapshot(T o)36     public static <T> T maybeSnapshot(T o) {
37         if (o instanceof Snappable) {
38             return ((Snappable<T>) o).snapshot();
39         } else {
40             return o;
41         }
42     }
43 
44     /**
45      * Copy a SparseArray in a manner suitable for a snapshot.  The destination must be
46      * empty.  This is not a snapshot because the elements are copied by reference even if
47      * they are {@link Snappable}.
48      * @param dst The destination array.  It must be empty.
49      * @param src The source array
50      */
copy(@onNull SparseArray<E> dst, @NonNull SparseArray<E> src)51     public static <E> void copy(@NonNull SparseArray<E> dst, @NonNull SparseArray<E> src) {
52         if (dst.size() != 0) {
53             throw new IllegalArgumentException("copy destination is not empty");
54         }
55         final int end = src.size();
56         for (int i = 0; i < end; i++) {
57             dst.put(src.keyAt(i), src.valueAt(i));
58         }
59     }
60 
61     /**
62      * Copy a SparseSetArray in a manner suitable for a snapshot.  The destination must be
63      * empty.  This is not a snapshot because the elements are copied by reference even if
64      * they are {@link Snappable}.
65      * @param dst The destination array.  It must be empty.
66      * @param src The source array
67      */
copy(@onNull SparseSetArray<E> dst, @NonNull SparseSetArray<E> src)68     public static <E> void copy(@NonNull SparseSetArray<E> dst, @NonNull SparseSetArray<E> src) {
69         if (dst.size() != 0) {
70             throw new IllegalArgumentException("copy destination is not empty");
71         }
72         final int end = src.size();
73         for (int i = 0; i < end; i++) {
74             final int size = src.sizeAt(i);
75             for (int j = 0; j < size; j++) {
76                 dst.add(src.keyAt(i), src.valueAt(i, j));
77             }
78         }
79     }
80 
81     /**
82      * Make <dst> a snapshot of <src> .
83      * @param dst The destination array.  It must be empty.
84      * @param src The source array
85      */
snapshot(@onNull SparseIntArray dst, @NonNull SparseIntArray src)86     public static void snapshot(@NonNull SparseIntArray dst, @NonNull SparseIntArray src) {
87         if (dst.size() != 0) {
88             throw new IllegalArgumentException("snapshot destination is not empty");
89         }
90         final int end = src.size();
91         for (int i = 0; i < end; i++) {
92             dst.put(src.keyAt(i), src.valueAt(i));
93         }
94     }
95 
96     /**
97      * Make <dst> a "snapshot" of <src>.  <dst> mst be empty.  The destination is just a
98      * copy of the source except that if the source elements implement Snappable, then
99      * the elements in the destination will be snapshots of elements from the source.
100      * @param dst The destination array.  It must be empty.
101      * @param src The source array
102      */
snapshot(@onNull SparseArray<E> dst, @NonNull SparseArray<E> src)103     public static <E extends Snappable<E>> void snapshot(@NonNull SparseArray<E> dst,
104             @NonNull SparseArray<E> src) {
105         if (dst.size() != 0) {
106             throw new IllegalArgumentException("snapshot destination is not empty");
107         }
108         final int end = src.size();
109         for (int i = 0; i < end; i++) {
110             dst.put(src.keyAt(i), src.valueAt(i).snapshot());
111         }
112     }
113 
114     /**
115      * Make <dst> a "snapshot" of <src>.  <dst> mst be empty.  The destination is a
116      * copy of the source except that snapshots are taken of the elements.
117      * @param dst The destination array.  It must be empty.
118      * @param src The source array
119      */
snapshot(@onNull SparseSetArray<E> dst, @NonNull SparseSetArray<E> src)120     public static <E extends Snappable<E>> void snapshot(@NonNull SparseSetArray<E> dst,
121             @NonNull SparseSetArray<E> src) {
122         if (dst.size() != 0) {
123             throw new IllegalArgumentException("snapshot destination is not empty");
124         }
125         final int end = src.size();
126         for (int i = 0; i < end; i++) {
127             final int size = src.sizeAt(i);
128             for (int j = 0; j < size; j++) {
129                 dst.add(src.keyAt(i), src.valueAt(i, j).snapshot());
130             }
131         }
132     }
133 }
134