| // Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | package com.android.tools.r8.graph; | 
 |  | 
 | /** | 
 |  * Definitions of access control routines. | 
 |  * | 
 |  * <p>Follows SE 11, jvm spec, section 5.4.4 on "Access Control", except for aspects related to | 
 |  * "run-time module", for which all items are assumed to be in the same single such module. | 
 |  */ | 
 | public class AccessControl { | 
 |  | 
 |   public static boolean isClassAccessible(DexClass clazz, DexProgramClass context) { | 
 |     if (clazz.accessFlags.isPublic()) { | 
 |       return true; | 
 |     } | 
 |     return clazz.getType().isSamePackage(context.getType()); | 
 |   } | 
 |  | 
 |   public static boolean isMethodAccessible( | 
 |       DexEncodedMethod method, | 
 |       DexClass holder, | 
 |       DexProgramClass context, | 
 |       AppInfoWithSubtyping appInfo) { | 
 |     return isMemberAccessible(method.accessFlags, holder, context, appInfo); | 
 |   } | 
 |  | 
 |   public static boolean isFieldAccessible( | 
 |       DexEncodedField field, | 
 |       DexClass holder, | 
 |       DexProgramClass context, | 
 |       AppInfoWithSubtyping appInfo) { | 
 |     return isMemberAccessible(field.accessFlags, holder, context, appInfo); | 
 |   } | 
 |  | 
 |   private static boolean isMemberAccessible( | 
 |       AccessFlags<?> memberFlags, | 
 |       DexClass holder, | 
 |       DexProgramClass context, | 
 |       AppInfoWithSubtyping appInfo) { | 
 |     if (!isClassAccessible(holder, context)) { | 
 |       return false; | 
 |     } | 
 |     if (memberFlags.isPublic()) { | 
 |       return true; | 
 |     } | 
 |     if (memberFlags.isPrivate()) { | 
 |       return isNestMate(holder, context); | 
 |     } | 
 |     if (holder.getType().isSamePackage(context.getType())) { | 
 |       return true; | 
 |     } | 
 |     if (!memberFlags.isProtected()) { | 
 |       return false; | 
 |     } | 
 |     return appInfo.isSubtype(context.getType(), holder.getType()); | 
 |   } | 
 |  | 
 |   private static boolean isNestMate(DexClass clazz, DexProgramClass context) { | 
 |     if (clazz == context) { | 
 |       return true; | 
 |     } | 
 |     if (!clazz.isInANest() || !context.isInANest()) { | 
 |       return false; | 
 |     } | 
 |     return clazz.getNestHost() == context.getNestHost(); | 
 |   } | 
 | } |