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 com.google.android.startop.iorap;
18 
19 import android.os.Parcelable;
20 import android.os.Parcel;
21 
22 import android.annotation.IntDef;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.util.Objects;
27 
28 /**
29  * Notifications for iorapd specifying when a system-wide intent defaults change.<br /><br />
30  *
31  * Intent defaults provide a mechanism for an app to register itself as an automatic handler.
32  * For example the camera app might be registered as the default handler for
33  * {@link android.provider.MediaStore#INTENT_ACTION_STILL_IMAGE_CAMERA} intent. Subsequently,
34  * if an arbitrary other app requests for a still image camera photo to be taken, the system
35  * will launch the respective default camera app to be launched to handle that request.<br /><br />
36  *
37  * In some cases iorapd might need to know default intents, e.g. for boot-time pinning of
38  * applications that resolve from the default intent. If the application would now be resolved
39  * differently, iorapd would unpin the old application and pin the new application.<br /><br />
40  *
41  * @hide
42  */
43 public class AppIntentEvent implements Parcelable {
44 
45     /** @see android.content.Intent#CATEGORY_DEFAULT */
46     public static final int TYPE_DEFAULT_INTENT_CHANGED = 0;
47     private static final int TYPE_MAX = 0;
48 
49     /** @hide */
50     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
51             TYPE_DEFAULT_INTENT_CHANGED,
52     })
53     @Retention(RetentionPolicy.SOURCE)
54     public @interface Type {}
55 
56     @Type public final int type;
57 
58     public final ActivityInfo oldActivityInfo;
59     public final ActivityInfo newActivityInfo;
60 
61     // TODO: Probably need the corresponding action here as well.
62 
createDefaultIntentChanged(ActivityInfo oldActivityInfo, ActivityInfo newActivityInfo)63     public static AppIntentEvent createDefaultIntentChanged(ActivityInfo oldActivityInfo,
64             ActivityInfo newActivityInfo) {
65         return new AppIntentEvent(TYPE_DEFAULT_INTENT_CHANGED, oldActivityInfo,
66                 newActivityInfo);
67     }
68 
AppIntentEvent(@ype int type, ActivityInfo oldActivityInfo, ActivityInfo newActivityInfo)69     private AppIntentEvent(@Type int type, ActivityInfo oldActivityInfo,
70             ActivityInfo newActivityInfo) {
71         this.type = type;
72         this.oldActivityInfo = oldActivityInfo;
73         this.newActivityInfo = newActivityInfo;
74 
75         checkConstructorArguments();
76     }
77 
checkConstructorArguments()78     private void checkConstructorArguments() {
79         CheckHelpers.checkTypeInRange(type, TYPE_MAX);
80         Objects.requireNonNull(oldActivityInfo, "oldActivityInfo");
81         Objects.requireNonNull(oldActivityInfo, "newActivityInfo");
82     }
83 
84     @Override
toString()85     public String toString() {
86         return String.format("{oldActivityInfo: %s, newActivityInfo: %s}", oldActivityInfo,
87                 newActivityInfo);
88     }
89 
90     @Override
equals(Object other)91     public boolean equals(Object other) {
92         if (this == other) {
93             return true;
94         } else if (other instanceof AppIntentEvent) {
95             return equals((AppIntentEvent) other);
96         }
97         return false;
98     }
99 
equals(AppIntentEvent other)100     private boolean equals(AppIntentEvent other) {
101         return type == other.type &&
102                 Objects.equals(oldActivityInfo, other.oldActivityInfo) &&
103                 Objects.equals(newActivityInfo, other.newActivityInfo);
104     }
105 
106     //<editor-fold desc="Binder boilerplate">
107     @Override
writeToParcel(Parcel out, int flags)108     public void writeToParcel(Parcel out, int flags) {
109         out.writeInt(type);
110         oldActivityInfo.writeToParcel(out, flags);
111         newActivityInfo.writeToParcel(out, flags);
112     }
113 
AppIntentEvent(Parcel in)114     private AppIntentEvent(Parcel in) {
115         this.type = in.readInt();
116         this.oldActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
117         this.newActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
118 
119         checkConstructorArguments();
120     }
121 
122     @Override
describeContents()123     public int describeContents() {
124         return 0;
125     }
126 
127     public static final Parcelable.Creator<AppIntentEvent> CREATOR
128             = new Parcelable.Creator<AppIntentEvent>() {
129         public AppIntentEvent createFromParcel(Parcel in) {
130             return new AppIntentEvent(in);
131         }
132 
133         public AppIntentEvent[] newArray(int size) {
134             return new AppIntentEvent[size];
135         }
136     };
137     //</editor-fold>
138 }
139