1 /*
2  * Copyright (C) 2018 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 android.view;
18 
19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
20 
21 import android.annotation.Nullable;
22 import android.app.WindowConfiguration;
23 import android.app.WindowConfiguration.ActivityType;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.os.Parcel;
26 import android.os.Parcelable;
27 import android.util.ArraySet;
28 import android.util.SparseArray;
29 import android.view.WindowManager.TransitionType;
30 
31 /**
32  * Defines which animation types should be overridden by which remote animation.
33  *
34  * @hide
35  */
36 public class RemoteAnimationDefinition implements Parcelable {
37 
38     private final SparseArray<RemoteAnimationAdapterEntry> mTransitionAnimationMap;
39 
40     @UnsupportedAppUsage
RemoteAnimationDefinition()41     public RemoteAnimationDefinition() {
42         mTransitionAnimationMap = new SparseArray<>();
43     }
44 
45     /**
46      * Registers a remote animation for a specific transition.
47      *
48      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
49      * @param activityTypeFilter The remote animation only runs if an activity with type of this
50      *                           parameter is involved in the transition.
51      * @param adapter The adapter that described how to run the remote animation.
52      */
53     @UnsupportedAppUsage
addRemoteAnimation(@ransitionType int transition, @ActivityType int activityTypeFilter, RemoteAnimationAdapter adapter)54     public void addRemoteAnimation(@TransitionType int transition,
55             @ActivityType int activityTypeFilter, RemoteAnimationAdapter adapter) {
56         mTransitionAnimationMap.put(transition,
57                 new RemoteAnimationAdapterEntry(adapter, activityTypeFilter));
58     }
59 
60     /**
61      * Registers a remote animation for a specific transition without defining an activity type
62      * filter.
63      *
64      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
65      * @param adapter The adapter that described how to run the remote animation.
66      */
67     @UnsupportedAppUsage
addRemoteAnimation(@ransitionType int transition, RemoteAnimationAdapter adapter)68     public void addRemoteAnimation(@TransitionType int transition, RemoteAnimationAdapter adapter) {
69         addRemoteAnimation(transition, ACTIVITY_TYPE_UNDEFINED, adapter);
70     }
71 
72     /**
73      * Checks whether a remote animation for specific transition is defined.
74      *
75      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
76      * @param activityTypes The set of activity types of activities that are involved in the
77      *                      transition. Will be used for filtering.
78      * @return Whether this definition has defined a remote animation for the specified transition.
79      */
hasTransition(@ransitionType int transition, ArraySet<Integer> activityTypes)80     public boolean hasTransition(@TransitionType int transition, ArraySet<Integer> activityTypes) {
81         return getAdapter(transition, activityTypes) != null;
82     }
83 
84     /**
85      * Retrieves the remote animation for a specific transition.
86      *
87      * @param transition The transition type. Must be one of WindowManager.TRANSIT_* values.
88      * @param activityTypes The set of activity types of activities that are involved in the
89      *                      transition. Will be used for filtering.
90      * @return The remote animation adapter for the specified transition.
91      */
getAdapter(@ransitionType int transition, ArraySet<Integer> activityTypes)92     public @Nullable RemoteAnimationAdapter getAdapter(@TransitionType int transition,
93             ArraySet<Integer> activityTypes) {
94         final RemoteAnimationAdapterEntry entry = mTransitionAnimationMap.get(transition);
95         if (entry == null) {
96             return null;
97         }
98         if (entry.activityTypeFilter == ACTIVITY_TYPE_UNDEFINED
99                 || activityTypes.contains(entry.activityTypeFilter)) {
100             return entry.adapter;
101         } else {
102             return null;
103         }
104     }
105 
RemoteAnimationDefinition(Parcel in)106     public RemoteAnimationDefinition(Parcel in) {
107         final int size = in.readInt();
108         mTransitionAnimationMap = new SparseArray<>(size);
109         for (int i = 0; i < size; i++) {
110             final int transition = in.readInt();
111             final RemoteAnimationAdapterEntry entry = in.readTypedObject(
112                     RemoteAnimationAdapterEntry.CREATOR);
113             mTransitionAnimationMap.put(transition, entry);
114         }
115     }
116 
117     /**
118      * To be called by system_server to keep track which pid is running the remote animations inside
119      * this definition.
120      */
setCallingPidUid(int pid, int uid)121     public void setCallingPidUid(int pid, int uid) {
122         for (int i = mTransitionAnimationMap.size() - 1; i >= 0; i--) {
123             mTransitionAnimationMap.valueAt(i).adapter.setCallingPidUid(pid, uid);
124         }
125     }
126 
127     @Override
describeContents()128     public int describeContents() {
129         return 0;
130     }
131 
132     @Override
writeToParcel(Parcel dest, int flags)133     public void writeToParcel(Parcel dest, int flags) {
134         final int size = mTransitionAnimationMap.size();
135         dest.writeInt(size);
136         for (int i = 0; i < size; i++) {
137             dest.writeInt(mTransitionAnimationMap.keyAt(i));
138             dest.writeTypedObject(mTransitionAnimationMap.valueAt(i), flags);
139         }
140     }
141 
142     public static final @android.annotation.NonNull Creator<RemoteAnimationDefinition> CREATOR =
143             new Creator<RemoteAnimationDefinition>() {
144         public RemoteAnimationDefinition createFromParcel(Parcel in) {
145             return new RemoteAnimationDefinition(in);
146         }
147 
148         public RemoteAnimationDefinition[] newArray(int size) {
149             return new RemoteAnimationDefinition[size];
150         }
151     };
152 
153     private static class RemoteAnimationAdapterEntry implements Parcelable {
154 
155         final RemoteAnimationAdapter adapter;
156 
157         /**
158          * Only run the transition if one of the activities matches the filter.
159          * {@link WindowConfiguration.ACTIVITY_TYPE_UNDEFINED} means no filter
160          */
161         @ActivityType final int activityTypeFilter;
162 
RemoteAnimationAdapterEntry(RemoteAnimationAdapter adapter, int activityTypeFilter)163         RemoteAnimationAdapterEntry(RemoteAnimationAdapter adapter, int activityTypeFilter) {
164             this.adapter = adapter;
165             this.activityTypeFilter = activityTypeFilter;
166         }
167 
RemoteAnimationAdapterEntry(Parcel in)168         private RemoteAnimationAdapterEntry(Parcel in) {
169             adapter = in.readParcelable(RemoteAnimationAdapter.class.getClassLoader());
170             activityTypeFilter = in.readInt();
171         }
172 
173         @Override
writeToParcel(Parcel dest, int flags)174         public void writeToParcel(Parcel dest, int flags) {
175             dest.writeParcelable(adapter, flags);
176             dest.writeInt(activityTypeFilter);
177         }
178 
179         @Override
describeContents()180         public int describeContents() {
181             return 0;
182         }
183 
184         private static final @android.annotation.NonNull Creator<RemoteAnimationAdapterEntry> CREATOR
185                 = new Creator<RemoteAnimationAdapterEntry>() {
186 
187             @Override
188             public RemoteAnimationAdapterEntry createFromParcel(Parcel in) {
189                 return new RemoteAnimationAdapterEntry(in);
190             }
191 
192             @Override
193             public RemoteAnimationAdapterEntry[] newArray(int size) {
194                 return new RemoteAnimationAdapterEntry[size];
195             }
196         };
197     }
198 }
199