1 /*
2  * Copyright 2017 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.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
20 import static android.view.Display.INVALID_DISPLAY;
21 
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.app.ActivityThread.ActivityClientRecord;
25 import android.app.ClientTransactionHandler;
26 import android.content.res.CompatibilityInfo;
27 import android.content.res.Configuration;
28 import android.os.IBinder;
29 import android.os.Parcel;
30 import android.os.Trace;
31 import android.window.ActivityWindowInfo;
32 
33 import java.util.Objects;
34 
35 /**
36  * Activity configuration changed callback.
37  * @hide
38  */
39 public class ActivityConfigurationChangeItem extends ActivityTransactionItem {
40 
41     private Configuration mConfiguration;
42     private ActivityWindowInfo mActivityWindowInfo;
43 
44     @Override
preExecute(@onNull ClientTransactionHandler client)45     public void preExecute(@NonNull ClientTransactionHandler client) {
46         CompatibilityInfo.applyOverrideScaleIfNeeded(mConfiguration);
47         // Notify the client of an upcoming change in the token configuration. This ensures that
48         // batches of config change items only process the newest configuration.
49         client.updatePendingActivityConfiguration(getActivityToken(), mConfiguration);
50     }
51 
52     @Override
execute(@onNull ClientTransactionHandler client, @NonNull ActivityClientRecord r, @NonNull PendingTransactionActions pendingActions)53     public void execute(@NonNull ClientTransactionHandler client, @NonNull ActivityClientRecord r,
54             @NonNull PendingTransactionActions pendingActions) {
55         // TODO(lifecycler): detect if PIP or multi-window mode changed and report it here.
56         Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
57         client.handleActivityConfigurationChanged(r, mConfiguration, INVALID_DISPLAY,
58                 mActivityWindowInfo);
59         Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
60     }
61 
62     // ObjectPoolItem implementation
63 
ActivityConfigurationChangeItem()64     private ActivityConfigurationChangeItem() {}
65 
66     /** Obtain an instance initialized with provided params. */
67     @NonNull
obtain(@onNull IBinder activityToken, @NonNull Configuration config, @NonNull ActivityWindowInfo activityWindowInfo)68     public static ActivityConfigurationChangeItem obtain(@NonNull IBinder activityToken,
69             @NonNull Configuration config, @NonNull ActivityWindowInfo activityWindowInfo) {
70         ActivityConfigurationChangeItem instance =
71                 ObjectPool.obtain(ActivityConfigurationChangeItem.class);
72         if (instance == null) {
73             instance = new ActivityConfigurationChangeItem();
74         }
75         instance.setActivityToken(activityToken);
76         instance.mConfiguration = new Configuration(config);
77         instance.mActivityWindowInfo = new ActivityWindowInfo(activityWindowInfo);
78 
79         return instance;
80     }
81 
82     @Override
recycle()83     public void recycle() {
84         super.recycle();
85         mConfiguration = null;
86         mActivityWindowInfo = null;
87         ObjectPool.recycle(this);
88     }
89 
90 
91     // Parcelable implementation
92 
93     /** Write to Parcel. */
94     @Override
writeToParcel(@onNull Parcel dest, int flags)95     public void writeToParcel(@NonNull Parcel dest, int flags) {
96         super.writeToParcel(dest, flags);
97         dest.writeTypedObject(mConfiguration, flags);
98         dest.writeTypedObject(mActivityWindowInfo, flags);
99     }
100 
101     /** Read from Parcel. */
ActivityConfigurationChangeItem(@onNull Parcel in)102     private ActivityConfigurationChangeItem(@NonNull Parcel in) {
103         super(in);
104         mConfiguration = in.readTypedObject(Configuration.CREATOR);
105         mActivityWindowInfo = in.readTypedObject(ActivityWindowInfo.CREATOR);
106     }
107 
108     public static final @NonNull Creator<ActivityConfigurationChangeItem> CREATOR =
109             new Creator<>() {
110                 public ActivityConfigurationChangeItem createFromParcel(@NonNull Parcel in) {
111                     return new ActivityConfigurationChangeItem(in);
112                 }
113 
114                 public ActivityConfigurationChangeItem[] newArray(int size) {
115                     return new ActivityConfigurationChangeItem[size];
116                 }
117             };
118 
119     @Override
equals(@ullable Object o)120     public boolean equals(@Nullable Object o) {
121         if (this == o) {
122             return true;
123         }
124         if (!super.equals(o)) {
125             return false;
126         }
127         final ActivityConfigurationChangeItem other = (ActivityConfigurationChangeItem) o;
128         return Objects.equals(mConfiguration, other.mConfiguration)
129                 && Objects.equals(mActivityWindowInfo, other.mActivityWindowInfo);
130     }
131 
132     @Override
hashCode()133     public int hashCode() {
134         int result = 17;
135         result = 31 * result + super.hashCode();
136         result = 31 * result + Objects.hashCode(mConfiguration);
137         result = 31 * result + Objects.hashCode(mActivityWindowInfo);
138         return result;
139     }
140 
141     @Override
toString()142     public String toString() {
143         return "ActivityConfigurationChange{" + super.toString()
144                 + ",config=" + mConfiguration
145                 + ",activityWindowInfo=" + mActivityWindowInfo + "}";
146     }
147 }
148