1 /* 2 * Copyright (C) 2020 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.listeners; 18 19 import android.annotation.Nullable; 20 21 import java.util.Objects; 22 import java.util.concurrent.Executor; 23 import java.util.concurrent.atomic.AtomicBoolean; 24 25 /** 26 * A listener registration that stores its own key, and thus can remove itself. By default it will 27 * remove itself if any checked exception occurs on listener execution. 28 * 29 * @param <TKey> key type 30 * @param <TListener> listener type 31 */ 32 public abstract class RemovableListenerRegistration<TKey, TListener> extends 33 ListenerRegistration<TListener> { 34 35 @Nullable private volatile TKey mKey; 36 private final AtomicBoolean mRemoved = new AtomicBoolean(false); 37 RemovableListenerRegistration(Executor executor, TListener listener)38 protected RemovableListenerRegistration(Executor executor, TListener listener) { 39 super(executor, listener); 40 } 41 42 /** 43 * Must be implemented to return the {@link ListenerMultiplexer} this registration is registered 44 * with. Often this is easiest to accomplish by defining registration subclasses as non-static 45 * inner classes of the multiplexer they are to be used with. 46 */ getOwner()47 protected abstract ListenerMultiplexer<TKey, ? super TListener, ?, ?> getOwner(); 48 49 /** 50 * Returns the key associated with this registration. May not be invoked before 51 * {@link #onRegister(Object)} or after {@link #onUnregister()}. 52 */ getKey()53 protected final TKey getKey() { 54 return Objects.requireNonNull(mKey); 55 } 56 57 /** 58 * Convenience method equivalent to invoking {@link #remove(boolean)} with the 59 * {@code immediately} parameter set to true. 60 */ remove()61 public final void remove() { 62 remove(true); 63 } 64 65 /** 66 * Removes this registration. If the {@code immediately} parameter is true, all pending listener 67 * invocations will fail. If the {@code immediately} parameter is false, listener invocations 68 * that were scheduled before remove was invoked (including invocations scheduled within {@link 69 * #onRemove(boolean)}) will continue, but any listener invocations scheduled after remove was 70 * invoked will fail. 71 * 72 * <p>Only the first call to this method will ever go through (and so {@link #onRemove(boolean)} 73 * will only ever be invoked once). 74 * 75 * <p>Does nothing if invoked before {@link #onRegister()} or after {@link #onUnregister()}. 76 */ remove(boolean immediately)77 public final void remove(boolean immediately) { 78 TKey key = mKey; 79 if (key != null && !mRemoved.getAndSet(true)) { 80 onRemove(immediately); 81 if (immediately) { 82 getOwner().removeRegistration(key, this); 83 } else { 84 executeOperation(listener -> getOwner().removeRegistration(key, this)); 85 } 86 } 87 } 88 89 /** 90 * Invoked just before this registration is removed due to {@link #remove(boolean)}, on the same 91 * thread as the responsible {@link #remove(boolean)} call. 92 * 93 * <p>This method will only ever be invoked once, no matter how many calls to {@link 94 * #remove(boolean)} are made, as any registration can only be removed once. 95 */ onRemove(boolean immediately)96 protected void onRemove(boolean immediately) {} 97 98 @Override onRegister(Object key)99 protected final void onRegister(Object key) { 100 super.onRegister(key); 101 mKey = (TKey) Objects.requireNonNull(key); 102 onRegister(); 103 } 104 105 /** 106 * May be overridden by subclasses. Invoked when registration occurs. Invoked while holding the 107 * owning multiplexer's internal lock. 108 * 109 * <p>If overridden you must ensure the superclass method is invoked (usually as the first thing 110 * in the overridden method). 111 */ onRegister()112 protected void onRegister() {} 113 114 @Override onUnregister()115 protected void onUnregister() { 116 mKey = null; 117 super.onUnregister(); 118 } 119 } 120