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 android.app.servertransaction; 18 19 import static android.app.servertransaction.TransactionExecutorHelper.getActivityName; 20 21 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; 22 23 import static java.util.Objects.requireNonNull; 24 25 import android.annotation.CallSuper; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.app.ActivityThread.ActivityClientRecord; 29 import android.app.ClientTransactionHandler; 30 import android.os.IBinder; 31 import android.os.Parcel; 32 33 import com.android.internal.annotations.VisibleForTesting; 34 35 import java.io.PrintWriter; 36 import java.util.Objects; 37 38 /** 39 * An activity-targeting callback message to a client that can be scheduled and executed. 40 * It also provides nullity-free version of 41 * {@link #execute(ClientTransactionHandler, IBinder, PendingTransactionActions)} for child class 42 * to inherit. 43 * 44 * @see ClientTransaction 45 * @see ClientTransactionItem 46 * @see com.android.server.wm.ClientLifecycleManager 47 * @hide 48 */ 49 public abstract class ActivityTransactionItem extends ClientTransactionItem { 50 51 /** Target client activity. */ 52 @NonNull 53 private final IBinder mActivityToken; 54 ActivityTransactionItem(@onNull IBinder activityToken)55 public ActivityTransactionItem(@NonNull IBinder activityToken) { 56 mActivityToken = requireNonNull(activityToken); 57 } 58 59 @Override execute(@onNull ClientTransactionHandler client, @NonNull PendingTransactionActions pendingActions)60 public final void execute(@NonNull ClientTransactionHandler client, 61 @NonNull PendingTransactionActions pendingActions) { 62 final ActivityClientRecord r = getActivityClientRecord(client); 63 execute(client, r, pendingActions); 64 } 65 66 /** 67 * Like {@link #execute(ClientTransactionHandler, PendingTransactionActions)}, 68 * but take non-null {@link ActivityClientRecord} as a parameter. 69 */ 70 @VisibleForTesting(visibility = PACKAGE) execute(@onNull ClientTransactionHandler client, @NonNull ActivityClientRecord r, @NonNull PendingTransactionActions pendingActions)71 public abstract void execute(@NonNull ClientTransactionHandler client, 72 @NonNull ActivityClientRecord r, @NonNull PendingTransactionActions pendingActions); 73 74 /** 75 * Gets the {@link ActivityClientRecord} instance that this transaction item is for. 76 * @param client Target client handler. 77 * @return The {@link ActivityClientRecord} instance that this transaction item is for. 78 */ 79 @NonNull getActivityClientRecord(@onNull ClientTransactionHandler client)80 final ActivityClientRecord getActivityClientRecord(@NonNull ClientTransactionHandler client) { 81 final ActivityClientRecord r = client.getActivityClient(getActivityToken()); 82 if (r == null) { 83 throw new IllegalArgumentException("Activity client record must not be null to execute " 84 + "transaction item: " + this); 85 } 86 if (client.getActivity(getActivityToken()) == null) { 87 throw new IllegalArgumentException("Activity must not be null to execute " 88 + "transaction item: " + this); 89 } 90 return r; 91 } 92 93 @VisibleForTesting(visibility = PACKAGE) 94 @NonNull 95 @Override getActivityToken()96 public IBinder getActivityToken() { 97 return mActivityToken; 98 } 99 100 // Parcelable implementation 101 102 /** Writes to Parcel. */ 103 @CallSuper 104 @Override writeToParcel(@onNull Parcel dest, int flags)105 public void writeToParcel(@NonNull Parcel dest, int flags) { 106 dest.writeStrongBinder(mActivityToken); 107 } 108 109 /** Reads from Parcel. */ ActivityTransactionItem(@onNull Parcel in)110 ActivityTransactionItem(@NonNull Parcel in) { 111 this(in.readStrongBinder()); 112 } 113 114 @Override dump(@onNull String prefix, @NonNull PrintWriter pw, @NonNull ClientTransactionHandler transactionHandler)115 void dump(@NonNull String prefix, @NonNull PrintWriter pw, 116 @NonNull ClientTransactionHandler transactionHandler) { 117 super.dump(prefix, pw, transactionHandler); 118 pw.append(prefix).append("Target activity: ") 119 .println(getActivityName(mActivityToken, transactionHandler)); 120 } 121 122 // Subclass must override and call super.equals to compare the mActivityToken. 123 @SuppressWarnings("EqualsGetClass") 124 @CallSuper 125 @Override equals(@ullable Object o)126 public boolean equals(@Nullable Object o) { 127 if (this == o) { 128 return true; 129 } 130 if (o == null || getClass() != o.getClass()) { 131 return false; 132 } 133 final ActivityTransactionItem other = (ActivityTransactionItem) o; 134 return Objects.equals(mActivityToken, other.mActivityToken); 135 } 136 137 @CallSuper 138 @Override hashCode()139 public int hashCode() { 140 return Objects.hashCode(mActivityToken); 141 } 142 143 @CallSuper 144 @Override toString()145 public String toString() { 146 return "mActivityToken=" + mActivityToken; 147 } 148 } 149