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.app.job.JobParameters;
20 import android.annotation.NonNull;
21 import android.os.Parcelable;
22 import android.os.Parcel;
23 
24 import android.annotation.IntDef;
25 
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 
29 /**
30  * Forward JobService events to iorapd. <br /><br />
31  *
32  * iorapd sometimes need to use background jobs. Forwarding these events to iorapd
33  * notifies iorapd when it is an opportune time to execute these background jobs.
34  *
35  * @hide
36  */
37 public class JobScheduledEvent implements Parcelable {
38 
39     /** JobService#onJobStarted */
40     public static final int TYPE_START_JOB = 0;
41     /** JobService#onJobStopped */
42     public static final int TYPE_STOP_JOB = 1;
43     private static final int TYPE_MAX = 1;
44 
45     /** @hide */
46     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
47             TYPE_START_JOB,
48             TYPE_STOP_JOB,
49     })
50     @Retention(RetentionPolicy.SOURCE)
51     public @interface Type {}
52 
53     @Type public final int type;
54 
55     /** @see JobParameters#getJobId() */
56     public final int jobId;
57 
58     public final String packageName;
59 
60     public final boolean shouldUpdateVersions;
61 
62     /** Device is 'idle' and it's charging (plugged in). */
63     public static final int SORT_IDLE_MAINTENANCE = 0;
64     private static final int SORT_MAX = 0;
65 
66     /** @hide */
67     @IntDef(flag = true, prefix = { "SORT_" }, value = {
68             SORT_IDLE_MAINTENANCE,
69     })
70     @Retention(RetentionPolicy.SOURCE)
71     public @interface Sort {}
72 
73     /**
74      * Roughly corresponds to the {@code extras} fields in a JobParameters.
75      */
76     @Sort public final int sort;
77 
78     /**
79      * Creates a {@link #SORT_IDLE_MAINTENANCE} event from the type and job parameters.
80      *
81      * Only the job ID is retained from {@code jobParams}, all other param info is dropped.
82      */
83     @NonNull
createIdleMaintenance( @ype int type, JobParameters jobParams, String packageName, boolean shouldUpdateVersions)84     public static JobScheduledEvent createIdleMaintenance(
85         @Type int type, JobParameters jobParams, String packageName, boolean shouldUpdateVersions) {
86         return new JobScheduledEvent(
87             type, jobParams.getJobId(), SORT_IDLE_MAINTENANCE, packageName, shouldUpdateVersions);
88     }
89 
JobScheduledEvent(@ype int type, int jobId, @Sort int sort, String packageName, boolean shouldUpdateVersions)90     private JobScheduledEvent(@Type int type,
91                               int jobId,
92                               @Sort int sort,
93                               String packageName,
94                               boolean shouldUpdateVersions) {
95         this.type = type;
96         this.jobId = jobId;
97         this.sort = sort;
98         this.packageName = packageName;
99         this.shouldUpdateVersions = shouldUpdateVersions;
100 
101         checkConstructorArguments();
102     }
103 
checkConstructorArguments()104     private void checkConstructorArguments() {
105         CheckHelpers.checkTypeInRange(type, TYPE_MAX);
106         // No check for 'jobId': any int is valid.
107         CheckHelpers.checkTypeInRange(sort, SORT_MAX);
108     }
109 
110     @Override
equals(Object other)111     public boolean equals(Object other) {
112         if (this == other) {
113             return true;
114         } else if (other instanceof JobScheduledEvent) {
115             return equals((JobScheduledEvent) other);
116         }
117         return false;
118     }
119 
equals(JobScheduledEvent other)120     private boolean equals(JobScheduledEvent other) {
121         return type == other.type &&
122                 jobId == other.jobId &&
123                 sort == other.sort &&
124                 packageName.equals(other.packageName) &&
125                 shouldUpdateVersions == other.shouldUpdateVersions;
126     }
127 
128     @Override
toString()129     public String toString() {
130         return String.format(
131             "{type: %d, jobId: %d, sort: %d, packageName: %s, shouldUpdateVersions %b}",
132             type, jobId, sort, packageName, shouldUpdateVersions);
133     }
134 
135     //<editor-fold desc="Binder boilerplate">
136     @Override
writeToParcel(Parcel out, int flags)137     public void writeToParcel(Parcel out, int flags) {
138         out.writeInt(type);
139         out.writeInt(jobId);
140         out.writeInt(sort);
141         out.writeString(packageName);
142         out.writeBoolean(shouldUpdateVersions);
143 
144         // We do not parcel the entire JobParameters here because there is no C++ equivalent
145         // of that class [which the iorapd side of the binder interface requires].
146     }
147 
JobScheduledEvent(Parcel in)148     private JobScheduledEvent(Parcel in) {
149         this.type = in.readInt();
150         this.jobId = in.readInt();
151         this.sort = in.readInt();
152         this.packageName = in.readString();
153         this.shouldUpdateVersions = in.readBoolean();
154 
155         checkConstructorArguments();
156     }
157 
158     @Override
describeContents()159     public int describeContents() {
160         return 0;
161     }
162 
163     public static final Parcelable.Creator<JobScheduledEvent> CREATOR
164             = new Parcelable.Creator<JobScheduledEvent>() {
165         public JobScheduledEvent createFromParcel(Parcel in) {
166             return new JobScheduledEvent(in);
167         }
168 
169         public JobScheduledEvent[] newArray(int size) {
170             return new JobScheduledEvent[size];
171         }
172     };
173     //</editor-fold>
174 }
175