• 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;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SpecialUsers.CanBeALL;
22 import android.annotation.UserIdInt;
23 import android.content.pm.Flags;
24 import android.content.pm.PackageManager;
25 
26 import dalvik.system.CloseGuard;
27 
28 import java.util.concurrent.atomic.AtomicBoolean;
29 
30 /**
31  * Class that freezes and kills the given package upon creation, and
32  * unfreezes it upon closing. This is typically used when doing surgery on
33  * app code/data to prevent the app from running while you're working.
34  */
35 final class PackageFreezer implements AutoCloseable {
36     @Nullable private InstallRequest mInstallRequest;
37 
38     private final String mPackageName;
39 
40     private final AtomicBoolean mClosed = new AtomicBoolean();
41     private final CloseGuard mCloseGuard = CloseGuard.get();
42 
43     @NonNull
44     private final PackageManagerService mPm;
45 
46     /**
47      * Create and return a stub freezer that doesn't actually do anything,
48      * typically used when someone requested
49      * {@link PackageManager#INSTALL_DONT_KILL_APP} or
50      * {@link PackageManager#DELETE_DONT_KILL_APP}.
51      */
52 
PackageFreezer(PackageManagerService pm, @Nullable InstallRequest request)53     PackageFreezer(PackageManagerService pm, @Nullable InstallRequest request) {
54         mPm = pm;
55         mPackageName = null;
56         mClosed.set(true);
57         mCloseGuard.open("close");
58         mInstallRequest = request;
59         // We only focus on the install Freeze metrics now
60         if (mInstallRequest != null) {
61             mInstallRequest.onFreezeStarted();
62         }
63     }
64 
PackageFreezer(String packageName, @CanBeALL @UserIdInt int userId, String killReason, PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request)65     PackageFreezer(String packageName, @CanBeALL @UserIdInt int userId, String killReason,
66             PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request) {
67         this(packageName, userId, killReason, pm, exitInfoReason, request, false);
68     }
69 
PackageFreezer(String packageName, @CanBeALL @UserIdInt int userId, String killReason, PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request, boolean waitAppKilled)70     PackageFreezer(String packageName, @CanBeALL @UserIdInt int userId, String killReason,
71             PackageManagerService pm, int exitInfoReason, @Nullable InstallRequest request,
72             boolean waitAppKilled) {
73         mPm = pm;
74         mPackageName = packageName;
75         mInstallRequest = request;
76         final PackageSetting ps;
77         // We only focus on the install Freeze metrics now
78         if (mInstallRequest != null) {
79             mInstallRequest.onFreezeStarted();
80         }
81         synchronized (mPm.mLock) {
82             final int refCounts = mPm.mFrozenPackages
83                     .getOrDefault(mPackageName, 0 /* defaultValue */) + 1;
84             mPm.mFrozenPackages.put(mPackageName, refCounts);
85             ps = mPm.mSettings.getPackageLPr(mPackageName);
86         }
87         if (ps != null) {
88             if (waitAppKilled && Flags.waitApplicationKilled()) {
89                 mPm.killApplicationSync(ps.getPackageName(), ps.getAppId(), userId, killReason,
90                         exitInfoReason);
91             } else {
92                 mPm.killApplication(ps.getPackageName(), ps.getAppId(), userId, killReason,
93                         exitInfoReason);
94             }
95         }
96         mCloseGuard.open("close");
97     }
98 
99     @Override
finalize()100     protected void finalize() throws Throwable {
101         try {
102             mCloseGuard.warnIfOpen();
103             close();
104         } finally {
105             super.finalize();
106         }
107     }
108 
109     @Override
close()110     public void close() {
111         mCloseGuard.close();
112         if (mClosed.compareAndSet(false, true)) {
113             synchronized (mPm.mLock) {
114                 final int refCounts = mPm.mFrozenPackages
115                         .getOrDefault(mPackageName, 0 /* defaultValue */) - 1;
116                 if (refCounts > 0) {
117                     mPm.mFrozenPackages.put(mPackageName, refCounts);
118                 } else {
119                     mPm.mFrozenPackages.remove(mPackageName);
120                 }
121             }
122         }
123         // We only focus on the install Freeze metrics now
124         if (mInstallRequest != null) {
125             mInstallRequest.onFreezeCompleted();
126             mInstallRequest = null;
127         }
128     }
129 }
130