1 /*
2  * Copyright (C) 2021 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.android.server.pm.pkg;
18 
19 import android.annotation.Nullable;
20 import android.content.pm.SuspendDialogInfo;
21 import android.os.BaseBundle;
22 import android.os.PersistableBundle;
23 import android.util.Slog;
24 
25 import com.android.modules.utils.TypedXmlPullParser;
26 import com.android.modules.utils.TypedXmlSerializer;
27 
28 import org.xmlpull.v1.XmlPullParser;
29 import org.xmlpull.v1.XmlPullParserException;
30 import org.xmlpull.v1.XmlSerializer;
31 
32 import java.io.IOException;
33 import java.util.Objects;
34 
35 /**
36  * Container to describe suspension parameters.
37  * @hide
38  */
39 public final class SuspendParams {
40 
41     private static final String LOG_TAG = "FrameworkPackageUserState";
42     private static final String TAG_DIALOG_INFO = "dialog-info";
43     private static final String TAG_APP_EXTRAS = "app-extras";
44     private static final String TAG_LAUNCHER_EXTRAS = "launcher-extras";
45 
46     private final SuspendDialogInfo dialogInfo;
47     private final PersistableBundle appExtras;
48     private final PersistableBundle launcherExtras;
49 
SuspendParams(SuspendDialogInfo dialogInfo, PersistableBundle appExtras, PersistableBundle launcherExtras)50     public SuspendParams(SuspendDialogInfo dialogInfo, PersistableBundle appExtras,
51             PersistableBundle launcherExtras) {
52         this.dialogInfo = dialogInfo;
53         this.appExtras = appExtras;
54         this.launcherExtras = launcherExtras;
55     }
56 
57     @Override
equals(@ullable Object obj)58     public boolean equals(@Nullable Object obj) {
59         if (this == obj) {
60             return true;
61         }
62         if (!(obj instanceof SuspendParams)) {
63             return false;
64         }
65         final SuspendParams other = (SuspendParams) obj;
66         if (!Objects.equals(dialogInfo, other.dialogInfo)) {
67             return false;
68         }
69         if (!BaseBundle.kindofEquals(appExtras, other.appExtras)) {
70             return false;
71         }
72         if (!BaseBundle.kindofEquals(launcherExtras, other.launcherExtras)) {
73             return false;
74         }
75         return true;
76     }
77 
78     @Override
hashCode()79     public int hashCode() {
80         int hashCode = Objects.hashCode(dialogInfo);
81         hashCode = 31 * hashCode + ((appExtras != null) ? appExtras.size() : 0);
82         hashCode = 31 * hashCode + ((launcherExtras != null) ? launcherExtras.size() : 0);
83         return hashCode;
84     }
85 
86     /**
87      * Serializes this object into an xml format
88      *
89      * @param out the {@link XmlSerializer} object
90      */
saveToXml(TypedXmlSerializer out)91     public void saveToXml(TypedXmlSerializer out) throws IOException {
92         if (dialogInfo != null) {
93             out.startTag(null, TAG_DIALOG_INFO);
94             dialogInfo.saveToXml(out);
95             out.endTag(null, TAG_DIALOG_INFO);
96         }
97         if (appExtras != null) {
98             out.startTag(null, TAG_APP_EXTRAS);
99             try {
100                 appExtras.saveToXml(out);
101             } catch (XmlPullParserException e) {
102                 Slog.e(LOG_TAG, "Exception while trying to write appExtras."
103                         + " Will be lost on reboot", e);
104             }
105             out.endTag(null, TAG_APP_EXTRAS);
106         }
107         if (launcherExtras != null) {
108             out.startTag(null, TAG_LAUNCHER_EXTRAS);
109             try {
110                 launcherExtras.saveToXml(out);
111             } catch (XmlPullParserException e) {
112                 Slog.e(LOG_TAG, "Exception while trying to write launcherExtras."
113                         + " Will be lost on reboot", e);
114             }
115             out.endTag(null, TAG_LAUNCHER_EXTRAS);
116         }
117     }
118 
119     /**
120      * Parses this object from the xml format. Returns {@code null} if no object related
121      * information could be read.
122      *
123      * @param in the reader
124      */
restoreFromXml(TypedXmlPullParser in)125     public static SuspendParams restoreFromXml(TypedXmlPullParser in) throws IOException {
126         SuspendDialogInfo readDialogInfo = null;
127         PersistableBundle readAppExtras = null;
128         PersistableBundle readLauncherExtras = null;
129 
130         final int currentDepth = in.getDepth();
131         int type;
132         try {
133             while ((type = in.next()) != XmlPullParser.END_DOCUMENT
134                     && (type != XmlPullParser.END_TAG
135                     || in.getDepth() > currentDepth)) {
136                 if (type == XmlPullParser.END_TAG
137                         || type == XmlPullParser.TEXT) {
138                     continue;
139                 }
140                 switch (in.getName()) {
141                     case TAG_DIALOG_INFO:
142                         readDialogInfo = SuspendDialogInfo.restoreFromXml(in);
143                         break;
144                     case TAG_APP_EXTRAS:
145                         readAppExtras = PersistableBundle.restoreFromXml(in);
146                         break;
147                     case TAG_LAUNCHER_EXTRAS:
148                         readLauncherExtras = PersistableBundle.restoreFromXml(in);
149                         break;
150                     default:
151                         Slog.w(LOG_TAG, "Unknown tag " + in.getName()
152                                 + " in SuspendParams. Ignoring");
153                         break;
154                 }
155             }
156         } catch (XmlPullParserException e) {
157             Slog.e(LOG_TAG, "Exception while trying to parse SuspendParams,"
158                     + " some fields may default", e);
159         }
160         return new SuspendParams(readDialogInfo, readAppExtras, readLauncherExtras);
161     }
162 
getDialogInfo()163     public SuspendDialogInfo getDialogInfo() {
164         return dialogInfo;
165     }
166 
getAppExtras()167     public PersistableBundle getAppExtras() {
168         return appExtras;
169     }
170 
getLauncherExtras()171     public PersistableBundle getLauncherExtras() {
172         return launcherExtras;
173     }
174 }
175