• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.mutate;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.content.ComponentName;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.PackageManager;
24 import android.content.pm.UserPackage;
25 import android.content.pm.overlay.OverlayPaths;
26 import android.util.ArraySet;
27 
28 import com.android.server.pm.PackageSetting;
29 import com.android.server.pm.pkg.PackageUserStateImpl;
30 import com.android.server.pm.pkg.SuspendParams;
31 
32 import java.util.concurrent.atomic.AtomicLong;
33 import java.util.function.Function;
34 
35 public class PackageStateMutator {
36 
37     private static final AtomicLong sStateChangeSequence = new AtomicLong();
38 
39     private final StateWriteWrapper mStateWrite = new StateWriteWrapper();
40 
41     private final Function<String, PackageSetting> mActiveStateFunction;
42     private final Function<String, PackageSetting> mDisabledStateFunction;
43 
44     private final ArraySet<PackageSetting> mChangedStates = new ArraySet<>();
45 
PackageStateMutator(@onNull Function<String, PackageSetting> activeStateFunction, @NonNull Function<String, PackageSetting> disabledStateFunction)46     public PackageStateMutator(@NonNull Function<String, PackageSetting> activeStateFunction,
47             @NonNull Function<String, PackageSetting> disabledStateFunction) {
48         mActiveStateFunction = activeStateFunction;
49         mDisabledStateFunction = disabledStateFunction;
50     }
51 
onPackageStateChanged()52     public static void onPackageStateChanged() {
53         sStateChangeSequence.incrementAndGet();
54     }
55 
56     @NonNull
forPackage(@onNull String packageName)57     public PackageStateWrite forPackage(@NonNull String packageName) {
58         return setState(mActiveStateFunction.apply(packageName));
59     }
60 
61     @Nullable
forPackageNullable(@onNull String packageName)62     public PackageStateWrite forPackageNullable(@NonNull String packageName) {
63         final PackageSetting packageState = mActiveStateFunction.apply(packageName);
64         setState(packageState);
65         if (packageState == null) {
66             return null;
67         }
68 
69         return setState(packageState);
70     }
71 
72     @NonNull
forDisabledSystemPackage(@onNull String packageName)73     public PackageStateWrite forDisabledSystemPackage(@NonNull String packageName) {
74         return setState(mDisabledStateFunction.apply(packageName));
75     }
76 
77     @Nullable
forDisabledSystemPackageNullable(@onNull String packageName)78     public PackageStateWrite forDisabledSystemPackageNullable(@NonNull String packageName) {
79         final PackageSetting packageState = mDisabledStateFunction.apply(packageName);
80         if (packageState == null) {
81             return null;
82         }
83 
84         return setState(packageState);
85     }
86 
87     @NonNull
initialState(int changedPackagesSequenceNumber)88     public InitialState initialState(int changedPackagesSequenceNumber) {
89         return new InitialState(changedPackagesSequenceNumber, sStateChangeSequence.get());
90     }
91 
92     /**
93      * @return null if initial state is null or if nothing has changed, otherwise return result
94      * with what changed
95      */
96     @Nullable
generateResult(@ullable InitialState state, int changedPackagesSequenceNumber)97     public Result generateResult(@Nullable InitialState state, int changedPackagesSequenceNumber) {
98         if (state == null) {
99             return Result.SUCCESS;
100         }
101 
102         boolean packagesChanged = changedPackagesSequenceNumber != state.mPackageSequence;
103         boolean stateChanged = sStateChangeSequence.get() != state.mStateSequence;
104         if (packagesChanged && stateChanged) {
105             return Result.PACKAGES_AND_STATE_CHANGED;
106         } else if (packagesChanged) {
107             return Result.PACKAGES_CHANGED;
108         } else if (stateChanged) {
109             return Result.STATE_CHANGED;
110         } else {
111             return Result.SUCCESS;
112         }
113     }
114 
onFinished()115     public void onFinished() {
116         for (int index = 0; index < mChangedStates.size(); index++) {
117             mChangedStates.valueAt(index).onChanged();
118         }
119     }
120 
121     @NonNull
setState(@ullable PackageSetting state)122     private StateWriteWrapper setState(@Nullable PackageSetting state) {
123         // State can be nullable because this infrastructure no-ops on non-existent states
124         if (state != null) {
125             mChangedStates.add(state);
126         }
127         return mStateWrite.setState(state);
128     }
129 
130     public static class InitialState {
131 
132         private final int mPackageSequence;
133         private final long mStateSequence;
134 
InitialState(int packageSequence, long stateSequence)135         public InitialState(int packageSequence, long stateSequence) {
136             mPackageSequence = packageSequence;
137             mStateSequence = stateSequence;
138         }
139     }
140 
141     public static class Result {
142 
143         public static final Result SUCCESS = new Result(true, false, false, false);
144         public static final Result PACKAGES_CHANGED = new Result(false, true, false, false);
145         public static final Result STATE_CHANGED = new Result(false, false, true, false);
146         public static final Result PACKAGES_AND_STATE_CHANGED = new Result(false, true, true, false);
147         public static final Result SPECIFIC_PACKAGE_NULL = new Result(false, false, true, true);
148 
149         private final boolean mCommitted;
150         private final boolean mPackagesChanged;
151         private final boolean mStateChanged;
152         private final boolean mSpecificPackageNull;
153 
Result(boolean committed, boolean packagesChanged, boolean stateChanged, boolean specificPackageNull)154         public Result(boolean committed, boolean packagesChanged, boolean stateChanged,
155                 boolean specificPackageNull) {
156             mCommitted = committed;
157             mPackagesChanged = packagesChanged;
158             mStateChanged = stateChanged;
159             mSpecificPackageNull = specificPackageNull;
160         }
161 
isCommitted()162         public boolean isCommitted() {
163             return mCommitted;
164         }
165 
isPackagesChanged()166         public boolean isPackagesChanged() {
167             return mPackagesChanged;
168         }
169 
isStateChanged()170         public boolean isStateChanged() {
171             return mStateChanged;
172         }
173 
isSpecificPackageNull()174         public boolean isSpecificPackageNull() {
175             return mSpecificPackageNull;
176         }
177     }
178 
179     private static class StateWriteWrapper implements PackageStateWrite {
180 
181         private final UserStateWriteWrapper mUserStateWrite = new UserStateWriteWrapper();
182 
183         @NonNull
184         private PackageSetting mState;
185 
setState(PackageSetting state)186         public StateWriteWrapper setState(PackageSetting state) {
187             this.mState = state;
188             return this;
189         }
190 
191         @NonNull
192         @Override
userState(int userId)193         public PackageUserStateWrite userState(int userId) {
194             var userState = mState == null ? null : mState.getOrCreateUserState(userId);
195             if (userState != null) {
196                 userState.setWatchable(mState);
197             }
198             return mUserStateWrite.setStates(userState);
199         }
200 
201         @Override
onChanged()202         public void onChanged() {
203             if (mState != null) {
204                 mState.onChanged();
205             }
206         }
207 
208         @Override
setLastPackageUsageTime(int reason, long timeInMillis)209         public PackageStateWrite setLastPackageUsageTime(int reason, long timeInMillis) {
210             if (mState != null) {
211                 mState.getTransientState().setLastPackageUsageTimeInMills(reason, timeInMillis);
212             }
213             return this;
214         }
215 
216         @Override
setHiddenUntilInstalled(boolean value)217         public PackageStateWrite setHiddenUntilInstalled(boolean value) {
218             if (mState != null) {
219                 mState.getTransientState().setHiddenUntilInstalled(value);
220             }
221             return this;
222         }
223 
224         @NonNull
225         @Override
setRequiredForSystemUser(boolean requiredForSystemUser)226         public PackageStateWrite setRequiredForSystemUser(boolean requiredForSystemUser) {
227             if (mState != null) {
228                 if (requiredForSystemUser) {
229                     mState.setPrivateFlags(mState.getPrivateFlags()
230                             | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
231                 } else {
232                     mState.setPrivateFlags(mState.getPrivateFlags()
233                             & ~ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
234                 }
235             }
236             return this;
237         }
238 
239         @NonNull
240         @Override
setMimeGroup(@onNull String mimeGroup, @NonNull ArraySet<String> mimeTypes)241         public PackageStateWrite setMimeGroup(@NonNull String mimeGroup,
242                 @NonNull ArraySet<String> mimeTypes) {
243             if (mState != null) {
244                 mState.setMimeGroup(mimeGroup, mimeTypes);
245             }
246             return this;
247         }
248 
249         @NonNull
250         @Override
setCategoryOverride(@pplicationInfo.Category int category)251         public PackageStateWrite setCategoryOverride(@ApplicationInfo.Category int category) {
252             if (mState != null) {
253                 mState.setCategoryOverride(category);
254             }
255             return this;
256         }
257 
258         @NonNull
259         @Override
setPageSizeAppCompatFlags( @pplicationInfo.PageSizeAppCompatFlags int mode)260         public PackageStateWrite setPageSizeAppCompatFlags(
261                 @ApplicationInfo.PageSizeAppCompatFlags int mode) {
262             if (mState != null) {
263                 mState.setPageSizeAppCompatFlags(mode);
264             }
265             return this;
266         }
267 
268         @NonNull
269         @Override
setUpdateAvailable(boolean updateAvailable)270         public PackageStateWrite setUpdateAvailable(boolean updateAvailable) {
271             if (mState != null) {
272                 mState.setUpdateAvailable(updateAvailable);
273             }
274             return this;
275         }
276 
277         @NonNull
278         @Override
setLoadingProgress(float progress)279         public PackageStateWrite setLoadingProgress(float progress) {
280             if (mState != null) {
281                 mState.setLoadingProgress(progress);
282             }
283             return this;
284         }
285 
286         @NonNull
287         @Override
setLoadingCompletedTime(long loadingCompletedTime)288         public PackageStateWrite setLoadingCompletedTime(long loadingCompletedTime) {
289             if (mState != null) {
290                 mState.setLoadingCompletedTime(loadingCompletedTime);
291             }
292             return this;
293         }
294 
295         @NonNull
296         @Override
setOverrideSeInfo(@ullable String newSeInfo)297         public PackageStateWrite setOverrideSeInfo(@Nullable String newSeInfo) {
298             if (mState != null) {
299                 mState.getTransientState().setOverrideSeInfo(newSeInfo);
300             }
301             return this;
302         }
303 
304         @NonNull
305         @Override
setInstaller(@ullable String installerPackageName, int installerPackageUid)306         public PackageStateWrite setInstaller(@Nullable String installerPackageName,
307                 int installerPackageUid) {
308             if (mState != null) {
309                 mState.setInstallerPackage(installerPackageName, installerPackageUid);
310             }
311             return this;
312         }
313 
314         @NonNull
315         @Override
setUpdateOwner(@onNull String updateOwnerPackageName)316         public PackageStateWrite setUpdateOwner(@NonNull String updateOwnerPackageName) {
317             if (mState != null) {
318                 mState.setUpdateOwnerPackage(updateOwnerPackageName);
319             }
320             return this;
321         }
322 
323         private static class UserStateWriteWrapper implements PackageUserStateWrite {
324 
325             @Nullable
326             private PackageUserStateImpl mUserState;
327 
setStates(@ullable PackageUserStateImpl userState)328             public UserStateWriteWrapper setStates(@Nullable PackageUserStateImpl userState) {
329                 mUserState = userState;
330                 return this;
331             }
332 
333             @NonNull
334             @Override
setInstalled(boolean installed)335             public PackageUserStateWrite setInstalled(boolean installed) {
336                 if (mUserState != null) {
337                     mUserState.setInstalled(installed);
338                 }
339                 return this;
340             }
341 
342             @NonNull
343             @Override
setUninstallReason(int reason)344             public PackageUserStateWrite setUninstallReason(int reason) {
345                 if (mUserState != null) {
346                     mUserState.setUninstallReason(reason);
347                 }
348                 return this;
349             }
350 
351             @NonNull
352             @Override
setDistractionFlags( @ackageManager.DistractionRestriction int restrictionFlags)353             public PackageUserStateWrite setDistractionFlags(
354                     @PackageManager.DistractionRestriction int restrictionFlags) {
355                 if (mUserState != null) {
356                     mUserState.setDistractionFlags(restrictionFlags);
357                 }
358                 return this;
359             }
360 
361             @NonNull
362             @Override
putSuspendParams(@onNull UserPackage suspendingPackage, @Nullable SuspendParams suspendParams)363             public PackageUserStateWrite putSuspendParams(@NonNull UserPackage suspendingPackage,
364                     @Nullable SuspendParams suspendParams) {
365                 if (mUserState != null) {
366                     mUserState.putSuspendParams(suspendingPackage, suspendParams);
367                 }
368                 return this;
369             }
370 
371             @NonNull
372             @Override
removeSuspension(@onNull UserPackage suspendingPackage)373             public PackageUserStateWrite removeSuspension(@NonNull UserPackage suspendingPackage) {
374                 if (mUserState != null) {
375                     mUserState.removeSuspension(suspendingPackage);
376                 }
377                 return this;
378             }
379 
380             @NonNull
381             @Override
setHidden(boolean hidden)382             public PackageUserStateWrite setHidden(boolean hidden) {
383                 if (mUserState != null) {
384                     mUserState.setHidden(hidden);
385                 }
386                 return this;
387             }
388 
389             @NonNull
390             @Override
setStopped(boolean stopped)391             public PackageUserStateWrite setStopped(boolean stopped) {
392                 if (mUserState != null) {
393                     mUserState.setStopped(stopped);
394                 }
395                 return this;
396             }
397 
398             @NonNull
399             @Override
setNotLaunched(boolean notLaunched)400             public PackageUserStateWrite setNotLaunched(boolean notLaunched) {
401                 if (mUserState != null) {
402                     mUserState.setNotLaunched(notLaunched);
403                 }
404                 return this;
405             }
406 
407             @NonNull
408             @Override
setOverlayPaths(@onNull OverlayPaths overlayPaths)409             public PackageUserStateWrite setOverlayPaths(@NonNull OverlayPaths overlayPaths) {
410                 if (mUserState != null) {
411                     mUserState.setOverlayPaths(overlayPaths);
412                 }
413                 return this;
414             }
415 
416             @NonNull
417             @Override
setOverlayPathsForLibrary(@onNull String libraryName, @Nullable OverlayPaths overlayPaths)418             public PackageUserStateWrite setOverlayPathsForLibrary(@NonNull String libraryName,
419                     @Nullable OverlayPaths overlayPaths) {
420                 if (mUserState != null) {
421                     mUserState.setSharedLibraryOverlayPaths(libraryName, overlayPaths);
422                 }
423                 return this;
424             }
425 
426             @NonNull
427             @Override
setHarmfulAppWarning(@ullable String warning)428             public PackageUserStateWrite setHarmfulAppWarning(@Nullable String warning) {
429                 if (mUserState != null) {
430                     mUserState.setHarmfulAppWarning(warning);
431                 }
432                 return this;
433             }
434 
435             @NonNull
436             @Override
setSplashScreenTheme(@ullable String theme)437             public PackageUserStateWrite setSplashScreenTheme(@Nullable String theme) {
438                 if (mUserState != null) {
439                     mUserState.setSplashScreenTheme(theme);
440                 }
441                 return this;
442             }
443 
444             @NonNull
445             @Override
setComponentLabelIcon(@onNull ComponentName componentName, @Nullable String nonLocalizedLabel, @Nullable Integer icon)446             public PackageUserStateWrite setComponentLabelIcon(@NonNull ComponentName componentName,
447                     @Nullable String nonLocalizedLabel, @Nullable Integer icon) {
448                 if (mUserState != null) {
449                     mUserState.overrideLabelAndIcon(componentName, nonLocalizedLabel, icon);
450                 }
451                 return null;
452             }
453 
454             @NonNull
455             @Override
setMinAspectRatio( @ackageManager.UserMinAspectRatio int aspectRatio)456             public PackageUserStateWrite setMinAspectRatio(
457                     @PackageManager.UserMinAspectRatio int aspectRatio) {
458                 if (mUserState != null) {
459                     mUserState.setMinAspectRatio(aspectRatio);
460                 }
461                 return this;
462             }
463         }
464     }
465 }
466