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 android.media.permission; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 22 /** 23 * An RAII-style object, used to establish a scope in which a single identity is part of the 24 * context. This is used in order to avoid having to explicitly pass identity information through 25 * deep call-stacks. 26 * <p> 27 * Intended usage: 28 * <pre> 29 * void caller() { 30 * Identity originator = ...; 31 * try (SafeCloseable ignored = IdentityContext.create(originator)) { 32 * // Within this scope the context is established. 33 * callee(); 34 * } 35 * // Outside the scope the context is restored to its prior state. 36 * 37 * void callee() { 38 * // Here we can access the identity without having to explicitly take it as an argument. 39 * // This is true even if this were a deeply nested call. 40 * Identity originator = IdentityContext.getNonNull(); 41 * ... 42 * } 43 * </pre> 44 * 45 * @hide 46 */ 47 public class IdentityContext implements SafeCloseable { 48 private static ThreadLocal<Identity> sThreadLocalIdentity = new ThreadLocal<>(); 49 private @Nullable Identity mPrior = get(); 50 51 /** 52 * Create a scoped identity context. 53 * 54 * @param identity The identity to establish with the scope. 55 * @return A {@link SafeCloseable}, to be used in a try-with-resources block to establish a 56 * scope. 57 */ 58 public static @NonNull create(@ullable Identity identity)59 SafeCloseable create(@Nullable Identity identity) { 60 return new IdentityContext(identity); 61 } 62 63 /** 64 * Get the current identity context. 65 * 66 * @return The identity, or null if it has not been established. 67 */ 68 public static @Nullable get()69 Identity get() { 70 return sThreadLocalIdentity.get(); 71 } 72 73 /** 74 * Get the current identity context. Throws a {@link NullPointerException} if it has not been 75 * established. 76 * 77 * @return The identity. 78 */ 79 public static @NonNull getNonNull()80 Identity getNonNull() { 81 Identity result = get(); 82 if (result == null) { 83 throw new NullPointerException("Identity context is not set"); 84 } 85 return result; 86 } 87 IdentityContext(@ullable Identity identity)88 private IdentityContext(@Nullable Identity identity) { 89 set(identity); 90 } 91 92 @Override close()93 public void close() { 94 set(mPrior); 95 } 96 set(@ullable Identity identity)97 private static void set(@Nullable Identity identity) { 98 sThreadLocalIdentity.set(identity); 99 } 100 } 101