• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.location.injector;
18 
19 import static com.android.server.location.LocationManagerService.D;
20 import static com.android.server.location.LocationManagerService.TAG;
21 
22 import android.util.Log;
23 
24 import com.android.internal.annotations.GuardedBy;
25 
26 import java.util.concurrent.CopyOnWriteArrayList;
27 
28 /** Helpers for tracking queries and resets of package state. */
29 public abstract class PackageResetHelper {
30 
31     /** Interface for responding to reset events. */
32     public interface Responder {
33 
34         /**
35          * Called when a package's runtime state is being reset for whatever reason and any
36          * components carrying runtime state on behalf of the package should clear that state.
37          *
38          * @param packageName The name of the package.
39          */
onPackageReset(String packageName)40         void onPackageReset(String packageName);
41 
42         /**
43          * Called when the system queries whether this package has any active state for the given
44          * package. Should return true if the component has some runtime state that is resetable of
45          * behalf of the given package, and false otherwise.
46          *
47          * @param packageName The name of the package.
48          * @return True if this component has resetable state for the given package.
49          */
isResetableForPackage(String packageName)50         boolean isResetableForPackage(String packageName);
51     }
52 
53     private final CopyOnWriteArrayList<Responder> mResponders;
54 
PackageResetHelper()55     public PackageResetHelper() {
56         mResponders = new CopyOnWriteArrayList<>();
57     }
58 
59     /** Begin listening for package reset events. */
register(Responder responder)60     public synchronized void register(Responder responder) {
61         boolean empty = mResponders.isEmpty();
62         mResponders.add(responder);
63         if (empty) {
64             onRegister();
65         }
66     }
67 
68     /** Stop listening for package reset events. */
unregister(Responder responder)69     public synchronized void unregister(Responder responder) {
70         mResponders.remove(responder);
71         if (mResponders.isEmpty()) {
72             onUnregister();
73         }
74     }
75 
76     @GuardedBy("this")
onRegister()77     protected abstract void onRegister();
78 
79     @GuardedBy("this")
onUnregister()80     protected abstract void onUnregister();
81 
notifyPackageReset(String packageName)82     protected final void notifyPackageReset(String packageName) {
83         if (D) {
84             Log.d(TAG, "package " + packageName + " reset");
85         }
86 
87         for (Responder responder : mResponders) {
88             responder.onPackageReset(packageName);
89         }
90     }
91 
queryResetableForPackage(String packageName)92     protected final boolean queryResetableForPackage(String packageName) {
93         for (Responder responder : mResponders) {
94             if (responder.isResetableForPackage(packageName)) {
95                 return true;
96             }
97         }
98 
99         return false;
100     }
101 }
102