1 /*
2  * Copyright 2019 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 package android.app.servertransaction;
17 
18 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
19 
20 import android.app.ActivityTaskManager;
21 import android.app.ClientTransactionHandler;
22 import android.os.IBinder;
23 import android.os.Parcel;
24 import android.os.RemoteException;
25 import android.os.Trace;
26 
27 /**
28  * Top resumed activity changed callback.
29  * @hide
30  */
31 public class TopResumedActivityChangeItem extends ClientTransactionItem {
32 
33     private boolean mOnTop;
34 
35     @Override
execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions)36     public void execute(ClientTransactionHandler client, IBinder token,
37             PendingTransactionActions pendingActions) {
38         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "topResumedActivityChangeItem");
39         client.handleTopResumedActivityChanged(token, mOnTop, "topResumedActivityChangeItem");
40         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
41     }
42 
43     @Override
postExecute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions)44     public void postExecute(ClientTransactionHandler client, IBinder token,
45             PendingTransactionActions pendingActions) {
46         if (mOnTop) {
47             return;
48         }
49 
50         // The loss of top resumed state can always be reported immediately in postExecute
51         // because only three cases are possible:
52         // 1. Activity is in RESUMED state now and it just handled the callback in #execute().
53         // 2. Activity wasn't RESUMED yet, which means that it didn't receive the top state yet.
54         // 3. Activity is PAUSED or in other lifecycle state after PAUSED. In this case top resumed
55         // state loss was already called right before pausing.
56         try {
57             ActivityTaskManager.getService().activityTopResumedStateLost();
58         } catch (RemoteException ex) {
59             throw ex.rethrowFromSystemServer();
60         }
61     }
62 
63 
64     // ObjectPoolItem implementation
65 
TopResumedActivityChangeItem()66     private TopResumedActivityChangeItem() {}
67 
68     /** Obtain an instance initialized with provided params. */
obtain(boolean onTop)69     public static TopResumedActivityChangeItem obtain(boolean onTop) {
70         TopResumedActivityChangeItem instance =
71                 ObjectPool.obtain(TopResumedActivityChangeItem.class);
72         if (instance == null) {
73             instance = new TopResumedActivityChangeItem();
74         }
75         instance.mOnTop = onTop;
76 
77         return instance;
78     }
79 
80     @Override
recycle()81     public void recycle() {
82         mOnTop = false;
83         ObjectPool.recycle(this);
84     }
85 
86 
87     // Parcelable implementation
88 
89     /** Write to Parcel. */
90     @Override
writeToParcel(Parcel dest, int flags)91     public void writeToParcel(Parcel dest, int flags) {
92         dest.writeBoolean(mOnTop);
93     }
94 
95     /** Read from Parcel. */
TopResumedActivityChangeItem(Parcel in)96     private TopResumedActivityChangeItem(Parcel in) {
97         mOnTop = in.readBoolean();
98     }
99 
100     public static final @android.annotation.NonNull Creator<TopResumedActivityChangeItem> CREATOR =
101             new Creator<TopResumedActivityChangeItem>() {
102                 public TopResumedActivityChangeItem createFromParcel(Parcel in) {
103                     return new TopResumedActivityChangeItem(in);
104                 }
105 
106                 public TopResumedActivityChangeItem[] newArray(int size) {
107                     return new TopResumedActivityChangeItem[size];
108                 }
109             };
110 
111     @Override
equals(Object o)112     public boolean equals(Object o) {
113         if (this == o) {
114             return true;
115         }
116         if (o == null || getClass() != o.getClass()) {
117             return false;
118         }
119         final TopResumedActivityChangeItem other = (TopResumedActivityChangeItem) o;
120         return mOnTop == other.mOnTop;
121     }
122 
123     @Override
hashCode()124     public int hashCode() {
125         int result = 17;
126         result = 31 * result + (mOnTop ? 1 : 0);
127         return result;
128     }
129 
130     @Override
toString()131     public String toString() {
132         return "TopResumedActivityChangeItem{onTop=" + mOnTop + "}";
133     }
134 }
135