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