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