signature:
public class ResTable_config { /** * Returns a map of the configuration parts for { @ link # toString } .
 * If a configuration part is not defined for this { @ link ResTable _ config } , its value
 * will be the empty string . */
public final Map < Type , String > toStringParts ( ) { } }

implementation:
Map < Type , String > result = new LinkedHashMap < > ( ) ; // Preserve order for # toString ( ) .
result . put ( Type . MCC , mcc != 0 ? "mcc" + mcc : "" ) ; result . put ( Type . MNC , mnc != 0 ? "mnc" + mnc : "" ) ; result . put ( Type . LANGUAGE_STRING , languageString ( ) ) ; result . put ( Type . LOCALE_SCRIPT_STRING , localeScriptString ( ) ) ; result . put ( Type . REGION_STRING , ! regionString ( ) . isEmpty ( ) ? "r" + regionString ( ) : "" ) ; result . put ( Type . LOCALE_VARIANT_STRING , localeVariantString ( ) ) ; result . put ( Type . SCREEN_LAYOUT_DIRECTION , getOrDefault ( SCREENLAYOUT_LAYOUTDIR_VALUES , screenLayoutDirection ( ) , "" ) ) ; result . put ( Type . SMALLEST_SCREEN_WIDTH_DP , smallestScreenWidthDp != 0 ? "sw" + smallestScreenWidthDp + "dp" : "" ) ; result . put ( Type . SCREEN_WIDTH_DP , screenWidthDp != 0 ? "w" + screenWidthDp + "dp" : "" ) ; result . put ( Type . SCREEN_HEIGHT_DP , screenHeightDp != 0 ? "h" + screenHeightDp + "dp" : "" ) ; result . put ( Type . SCREEN_LAYOUT_SIZE , getOrDefault ( SCREENLAYOUT_SIZE_VALUES , screenLayoutSize ( ) , "" ) ) ; result . put ( Type . SCREEN_LAYOUT_LONG , getOrDefault ( SCREENLAYOUT_LONG_VALUES , screenLayoutLong ( ) , "" ) ) ; result . put ( Type . SCREEN_LAYOUT_ROUND , getOrDefault ( SCREENLAYOUT_ROUND_VALUES , screenLayoutRound ( ) , "" ) ) ; result . put ( Type . COLOR_MODE_HDR , getOrDefault ( COLOR_MODE_HDR_VALUES , colorModeHdr ( ) , "" ) ) ; result . put ( Type . COLOR_MODE_WIDE_COLOR_GAMUT , getOrDefault ( COLOR_MODE_WIDE_COLOR_GAMUT_VALUES , colorModeWideColorGamut ( ) , "" ) ) ; result . put ( Type . ORIENTATION , getOrDefault ( ORIENTATION_VALUES , orientation , "" ) ) ; result . put ( Type . UI_MODE_TYPE , getOrDefault ( UI_MODE_TYPE_VALUES , uiModeType ( ) , "" ) ) ; result . put ( Type . UI_MODE_NIGHT , getOrDefault ( UI_MODE_NIGHT_VALUES , uiModeNight ( ) , "" ) ) ; result . put ( Type . DENSITY_DPI , getOrDefault ( DENSITY_DPI_VALUES , density , density + "dpi" ) ) ; result . put ( Type . TOUCHSCREEN , getOrDefault ( TOUCHSCREEN_VALUES , touchscreen , "" ) ) ; result . put ( Type . KEYBOARD_HIDDEN , getOrDefault ( KEYBOARDHIDDEN_VALUES , keyboardHidden ( ) , "" ) ) ; result . put ( Type . KEYBOARD , getOrDefault ( KEYBOARD_VALUES , keyboard , "" ) ) ; result . put ( Type . NAVIGATION_HIDDEN , getOrDefault ( NAVIGATIONHIDDEN_VALUES , navigationHidden ( ) , "" ) ) ; result . put ( Type . NAVIGATION , getOrDefault ( NAVIGATION_VALUES , navigation , "" ) ) ; result . put ( Type . SCREEN_SIZE , screenWidth != 0 || screenHeight != 0 ? screenWidth + "x" + screenHeight : "" ) ; String sdkVersion = "" ; if ( this . sdkVersion != 0 ) { sdkVersion = "v" + this . sdkVersion ; if ( minorVersion != 0 ) { sdkVersion += "." + minorVersion ; } } result . put ( Type . SDK_VERSION , sdkVersion ) ; return result ;


signature:
public class ResTable_config { /** * boolean match ( final ResTable _ config settings ) {
 * System . out . println ( this + " . match ( " + settings + " ) " ) ;
 * boolean result = match _ ( settings ) ;
 * System . out . println ( " - > " + result ) ;
 * return result ; */
public boolean match ( final ResTable_config settings ) { } }

implementation:
if ( imsi ( ) != 0 ) { if ( mcc != 0 && mcc != settings . mcc ) { return false ; } if ( mnc != 0 && mnc != settings . mnc ) { return false ; } } if ( locale ( ) != 0 ) { // Don ' t consider country and variants when deciding matches .
// ( Theoretically , the variant can also affect the script . For
// example , " ar - alalc97 " probably implies the Latin script , but since
// CLDR doesn ' t support getting likely scripts for that , we ' ll assume
// the variant doesn ' t change the script . )
// If two configs differ only in their country and variant ,
// they can be weeded out in the isMoreSpecificThan test .
if ( ! langsAreEquivalent ( language , settings . language ) ) { return false ; } // For backward compatibility and supporting private - use locales , we
// fall back to old behavior if we couldn ' t determine the script for
// either of the desired locale or the provided locale . But if we could determine
// the scripts , they should be the same for the locales to match .
boolean countriesMustMatch = false ; byte [ ] computed_script = new byte [ 4 ] ; byte [ ] script = null ; if ( settings . localeScript [ 0 ] == '\0' ) { // could not determine the request ' s script
countriesMustMatch = true ; } else { if ( localeScript [ 0 ] == '\0' && ! localeScriptWasComputed ) { // script was not provided or computed , so we try to compute it
localeDataComputeScript ( computed_script , language , country ) ; if ( computed_script [ 0 ] == '\0' ) { // we could not compute the script
countriesMustMatch = true ; } else { script = computed_script ; } } else { // script was provided , so just use it
script = localeScript ; } } if ( countriesMustMatch ) { if ( country [ 0 ] != '\0' && ! areIdentical ( country , settings . country ) ) { return false ; } } else { if ( ! Arrays . equals ( script , settings . localeScript ) ) { return false ; } } } if ( screenConfig ( ) != 0 ) { final int layoutDir = screenLayout & MASK_LAYOUTDIR ; final int setLayoutDir = settings . screenLayout & MASK_LAYOUTDIR ; if ( layoutDir != 0 && layoutDir != setLayoutDir ) { return false ; } final int screenSize = screenLayout & MASK_SCREENSIZE ; final int setScreenSize = settings . screenLayout & MASK_SCREENSIZE ; // Any screen sizes for larger screens than the setting do not
// match .
if ( screenSize != 0 && screenSize > setScreenSize ) { return false ; } final int screenLong = screenLayout & MASK_SCREENLONG ; final int setScreenLong = settings . screenLayout & MASK_SCREENLONG ; if ( screenLong != 0 && screenLong != setScreenLong ) { return false ; } final int uiModeType = uiMode & MASK_UI_MODE_TYPE ; final int setUiModeType = settings . uiMode & MASK_UI_MODE_TYPE ; if ( uiModeType != 0 && uiModeType != setUiModeType ) { return false ; } final int uiModeNight = uiMode & MASK_UI_MODE_NIGHT ; final int setUiModeNight = settings . uiMode & MASK_UI_MODE_NIGHT ; if ( uiModeNight != 0 && uiModeNight != setUiModeNight ) { return false ; } if ( smallestScreenWidthDp != 0 && smallestScreenWidthDp > settings . smallestScreenWidthDp ) { return false ; } } if ( screenConfig2 ( ) != 0 ) { final int screenRound = screenLayout2 & MASK_SCREENROUND ; final int setScreenRound = settings . screenLayout2 & MASK_SCREENROUND ; if ( screenRound != 0 && screenRound != setScreenRound ) { return false ; } } final int hdr = colorMode & MASK_HDR ; final int setHdr = settings . colorMode & MASK_HDR ; if ( hdr != 0 && hdr != setHdr ) { return false ; } final int wideColorGamut = colorMode & MASK_WIDE_COLOR_GAMUT ; final int setWideColorGamut = settings . colorMode & MASK_WIDE_COLOR_GAMUT ; if ( wideColorGamut != 0 && wideColorGamut != setWideColorGamut ) { return false ; } if ( screenSizeDp ( ) != 0 ) { if ( screenWidthDp != 0 && screenWidthDp > settings . screenWidthDp ) { if ( kDebugTableSuperNoisy ) { ALOGI ( "Filtering out width %d in requested %d" , screenWidthDp , settings . screenWidthDp ) ; } return false ; } if ( screenHeightDp != 0 && screenHeightDp > settings . screenHeightDp ) { if ( kDebugTableSuperNoisy ) { ALOGI ( "Filtering out height %d in requested %d" , screenHeightDp , settings . screenHeightDp ) ; } return false ; } } if ( screenType ( ) != 0 ) { if ( orientation != 0 && orientation != settings . orientation ) { return false ; } // density always matches - we can scale it . See isBetterThan
if ( touchscreen != 0 && touchscreen != settings . touchscreen ) { return false ; } } if ( input ( ) != 0 ) { final int keysHidden = inputFlags & MASK_KEYSHIDDEN ; final int setKeysHidden = settings . inputFlags & MASK_KEYSHIDDEN ; if ( keysHidden != 0 && keysHidden != setKeysHidden ) { // For compatibility , we count a request for KEYSHIDDEN _ NO as also
// matching the more recent KEYSHIDDEN _ SOFT . Basically
// KEYSHIDDEN _ NO means there is some kind of keyboard available .
if ( kDebugTableSuperNoisy ) { ALOGI ( "Matching keysHidden: have=%d, config=%d\n" , keysHidden , setKeysHidden ) ; } if ( keysHidden != KEYSHIDDEN_NO || setKeysHidden != KEYSHIDDEN_SOFT ) { if ( kDebugTableSuperNoisy ) { ALOGI ( "No match!" ) ; } return false ; } } final int navHidden = inputFlags & MASK_NAVHIDDEN ; final int setNavHidden = settings . inputFlags & MASK_NAVHIDDEN ; if ( navHidden != 0 && navHidden != setNavHidden ) { return false ; } if ( keyboard != 0 && keyboard != settings . keyboard ) { return false ; } if ( navigation != 0 && navigation != settings . navigation ) { return false ; } } if ( screenSize ( ) != 0 ) { if ( screenWidth != 0 && screenWidth > settings . screenWidth ) { return false ; } if ( screenHeight != 0 && screenHeight > settings . screenHeight ) { return false ; } } if ( version ( ) != 0 ) { if ( sdkVersion != 0 && sdkVersion > settings . sdkVersion ) { return false ; } if ( minorVersion != 0 && minorVersion != settings . minorVersion ) { return false ; } } return true ;


signature:
public class ResTable_config { /** * void ResTable _ config : : getBcp47Locale ( char str [ RESTABLE _ MAX _ LOCALE _ LEN ] , bool canonicalize ) const { */
String getBcp47Locale ( boolean canonicalize ) { } }

implementation:
StringBuilder str = new StringBuilder ( ) ; // This represents the " any " locale value , which has traditionally been
// represented by the empty string .
if ( language [ 0 ] == '\0' && country [ 0 ] == '\0' ) { return "" ; } if ( language [ 0 ] != '\0' ) { if ( canonicalize && areIdentical ( language , kTagalog ) ) { // Replace Tagalog with Filipino if we are canonicalizing
str . setLength ( 0 ) ; str . append ( "fil" ) ; // 3 - letter code for Filipino
} else { str . append ( unpackLanguage ( ) ) ; } } if ( isTruthy ( localeScript [ 0 ] ) && ! localeScriptWasComputed ) { if ( str . length ( ) > 0 ) { str . append ( '-' ) ; } for ( byte aLocaleScript : localeScript ) { str . append ( ( char ) aLocaleScript ) ; } } if ( country [ 0 ] != '\0' ) { if ( str . length ( ) > 0 ) { str . append ( '-' ) ; } String regionStr = unpackRegion ( ) ; str . append ( regionStr ) ; } if ( isTruthy ( localeVariant [ 0 ] ) ) { if ( str . length ( ) > 0 ) { str . append ( '-' ) ; } for ( byte aLocaleScript : localeVariant ) { str . append ( ( char ) aLocaleScript ) ; } } // Add Unicode extension only if at least one other locale component is present
if ( localeNumberingSystem [ 0 ] != '\0' && str . length ( ) > 0 ) { String NU_PREFIX = "-u-nu-" ; str . append ( NU_PREFIX ) ; str . append ( new String ( localeNumberingSystem , UTF_8 ) ) ; } return str . toString ( ) ;


signature:
public class ShadowDrawerLayout { /** * Drawer animations are disabled in unit tests . */
@ Implementation protected void openDrawer ( View drawerView , boolean animate ) { } }

implementation: directlyOn ( realDrawerLayout , DrawerLayout . class ) . openDrawer ( drawerView , false ) ;


signature:
public class ShadowDrawerLayout { /** * Drawer animations are disabled in unit tests . */
@ Implementation protected void closeDrawer ( View drawerView , boolean animate ) { } }

implementation: directlyOn ( realDrawerLayout , DrawerLayout . class ) . closeDrawer ( drawerView , false ) ;


signature:
public class ShadowStatFs { /** * Register stats for a path , which will be used when a matching { @ link StatFs } instance is
 * created .
 * @ param path path to the file
 * @ param blockCount number of blocks
 * @ param freeBlocks number of free blocks
 * @ param availableBlocks number of available blocks */
public static void registerStats ( File path , int blockCount , int freeBlocks , int availableBlocks ) { } }

implementation: registerStats ( path . getAbsolutePath ( ) , blockCount , freeBlocks , availableBlocks ) ;


signature:
public class ShadowStatFs { /** * Register stats for a path , which will be used when a matching { @ link StatFs } instance is
 * created . A { @ link StatFs } instance matches if it extends path . If several registered paths
 * match , we pick the longest one .
 * @ param path path to the file
 * @ param blockCount number of blocks
 * @ param freeBlocks number of free blocks
 * @ param availableBlocks number of available blocks */
public static void registerStats ( String path , int blockCount , int freeBlocks , int availableBlocks ) { } }

implementation: stats . put ( path , new Stats ( blockCount , freeBlocks , availableBlocks ) ) ;


signature:
public class ShadowUserManager { /** * Compared to real Android , there is no check that the package name matches the application
 * package name and the method returns instantly .
 * @ see # setApplicationRestrictions ( String , Bundle ) */
@ Implementation ( minSdk = JELLY_BEAN_MR2 ) protected Bundle getApplicationRestrictions ( String packageName ) { } }

implementation: Bundle bundle = applicationRestrictions . get ( packageName ) ; return bundle != null ? bundle : new Bundle ( ) ;


signature:
public class ShadowUserManager { /** * Adds a profile associated for the user that the calling process is running on .
 * The user is assigned an arbitrary unique serial number .
 * @ return the user ' s serial number */
public long addUserProfile ( UserHandle userHandle ) { } }

implementation: long serialNumber = nextUserSerial ++ ; userProfiles . put ( userHandle , serialNumber ) ; return serialNumber ;


signature:
public class ShadowUserManager { /** * If any profiles have been added using { @ link # addProfile } , return those profiles .
 * Otherwise follow real android behaviour . */
@ Implementation ( minSdk = LOLLIPOP ) protected List < UserInfo > getProfiles ( int userHandle ) { } }

implementation: if ( profiles . containsKey ( userHandle ) ) { return ImmutableList . copyOf ( profiles . get ( userHandle ) ) ; } return directlyOn ( realObject , UserManager . class , "getProfiles" , ClassParameter . from ( int . class , userHandle ) ) ;


signature:
public class ShadowUserManager { /** * Add a profile to be returned by { @ link # getProfiles ( int ) } . * */
public void addProfile ( int userHandle , int profileUserHandle , String profileName , int profileFlags ) { } }

implementation: profiles . putIfAbsent ( userHandle , new ArrayList < > ( ) ) ; profiles . get ( userHandle ) . add ( new UserInfo ( profileUserHandle , profileName , profileFlags ) ) ;


signature:
public class ShadowUserManager { /** * Sets that the current user is a demo user ; controls the return value of { @ link
 * UserManager # isDemoUser ( ) } .
 * @ deprecated Use { @ link ShadowUserManager # addUser ( int , String , int ) } to create a demo user
 * instead of changing default user flags . */
@ Deprecated public void setIsDemoUser ( boolean isDemoUser ) { } }

implementation: UserInfo userInfo = getUserInfo ( UserHandle . myUserId ( ) ) ; if ( isDemoUser ) { userInfo . flags |= UserInfo . FLAG_DEMO ; } else { userInfo . flags &= ~ UserInfo . FLAG_DEMO ; }


signature:
public class ShadowUserManager { /** * Sets that the current user is the primary user ; controls the return value of { @ link
 * UserManager # isPrimaryUser ( ) } .
 * @ deprecated Use { @ link ShadowUserManager # addUser ( int , String , int ) } to create a primary user
 * instead of changing default user flags . */
@ Deprecated public void setIsPrimaryUser ( boolean isPrimaryUser ) { } }

implementation: UserInfo userInfo = getUserInfo ( UserHandle . myUserId ( ) ) ; if ( isPrimaryUser ) { userInfo . flags |= UserInfo . FLAG_PRIMARY ; } else { userInfo . flags &= ~ UserInfo . FLAG_PRIMARY ; }


signature:
public class ShadowUserManager { /** * Sets this process running under a restricted profile ; controls the return value of { @ link
 * UserManager # isRestrictedProfile ( ) } . */
public void setIsRestrictedProfile ( boolean isRestrictedProfile ) { } }

implementation: UserInfo userInfo = getUserInfo ( UserHandle . myUserId ( ) ) ; if ( isRestrictedProfile ) { userInfo . flags |= UserInfo . FLAG_RESTRICTED ; } else { userInfo . flags &= ~ UserInfo . FLAG_RESTRICTED ; }


signature:
public class ShadowUserManager { /** * Sets that the current user is the guest user ; controls the return value of { @ link
 * UserManager # isGuestUser ( ) } .
 * @ deprecated Use { @ link ShadowUserManager # addUser ( int , String , int ) } to create a guest user
 * instead of changing default user flags . */
@ Deprecated public void setIsGuestUser ( boolean isGuestUser ) { } }

implementation: UserInfo userInfo = getUserInfo ( UserHandle . myUserId ( ) ) ; if ( isGuestUser ) { userInfo . flags |= UserInfo . FLAG_GUEST ; } else { userInfo . flags &= ~ UserInfo . FLAG_GUEST ; }


signature:
public class ShadowUserManager { /** * Sets the current state for a given user , see { @ link UserManager # isUserRunning ( UserHandle ) }
 * and { @ link UserManager # isUserRunningOrStopping ( UserHandle ) } */
public void setUserState ( UserHandle handle , UserState state ) { } }

implementation: userState . put ( handle . getIdentifier ( ) , state ) ;


signature:
public class ShadowUserManager { /** * Switches the current user to { @ code userHandle } .
 * @ param userId the integer handle of the user , where 0 is the primary user . */
public void switchUser ( int userId ) { } }

implementation: if ( ! userInfoMap . containsKey ( userId ) ) { throw new UnsupportedOperationException ( "Must add user before switching to it" ) ; } ShadowProcess . setUid ( userPidMap . get ( userId ) ) ;


signature:
public class ShadowUserManager { /** * Creates a user with the specified name , userId and flags .
 * @ param id the unique id of user
 * @ param name name of the user
 * @ param flags 16 bits for user type . See { @ link UserInfo # flags }
 * @ return a handle to the new user */
public UserHandle addUser ( int id , String name , int flags ) { } }

implementation: UserHandle userHandle = id == UserHandle . USER_SYSTEM ? Process . myUserHandle ( ) : new UserHandle ( id ) ; addUserProfile ( userHandle ) ; setSerialNumberForUser ( userHandle , ( long ) id ) ; userInfoMap . put ( id , new UserInfo ( id , name , flags ) ) ; userPidMap . put ( id , id == UserHandle . USER_SYSTEM ? Process . myUid ( ) : id * UserHandle . PER_USER_RANGE + ShadowProcess . getRandomApplicationUid ( ) ) ; return userHandle ;


signature:
public class ShadowBluetoothSocket { /** * This method doesn ' t perform an actual connection and returns immediately */
@ Implementation protected void connect ( ) throws IOException { } }

implementation: if ( state == SocketState . CLOSED ) { throw new IOException ( "socket closed" ) ; } state = SocketState . CONNECTED ;


signature:
public class InvokeDynamicClassInstrumentor { /** * todo javadocs */
private void generateInvokeDynamic ( MutableClass mutableClass , MethodNode originalMethod , String originalMethodName , RobolectricGeneratorAdapter generator ) { } }

implementation: Handle original = new Handle ( getTag ( originalMethod ) , mutableClass . classType . getInternalName ( ) , originalMethod . name , originalMethod . desc ) ; if ( generator . isStatic ( ) ) { generator . loadArgs ( ) ; generator . invokeDynamic ( originalMethodName , originalMethod . desc , BOOTSTRAP_STATIC , original ) ; } else { String desc = "(" + mutableClass . classType . getDescriptor ( ) + originalMethod . desc . substring ( 1 ) ; generator . loadThis ( ) ; generator . loadArgs ( ) ; generator . invokeDynamic ( originalMethodName , desc , BOOTSTRAP , original ) ; } generator . returnValue ( ) ;


signature:
public class InvokeDynamicClassInstrumentor { /** * Intercepts the method using the invokedynamic bytecode instruction available in Java 7 + .
 * Should be called through interceptInvokeVirtualMethod , not directly . */
private void interceptInvokeVirtualMethodWithInvokeDynamic ( ListIterator < AbstractInsnNode > instructions , MethodInsnNode targetMethod ) { } }

implementation:
instructions . remove ( ) ; // remove the method invocation
Type type = Type . getObjectType ( targetMethod . owner ) ; String description = targetMethod . desc ; String owner = type . getClassName ( ) ; if ( targetMethod . getOpcode ( ) != Opcodes . INVOKESTATIC ) { String thisType = type . getDescriptor ( ) ; description = "(" + thisType + description . substring ( 1 ) ; } instructions . add ( new InvokeDynamicInsnNode ( targetMethod . name , description , BOOTSTRAP_INTRINSIC , owner ) ) ;


signature:
public class DynamicRefTable { /** * Adds mappings from the other DynamicRefTable */
int addMappings ( final DynamicRefTable other ) { } }

implementation:
if ( mAssignedPackageId != other . mAssignedPackageId ) { return UNKNOWN_ERROR ; } // final int entryCount = other . mEntries . size ( ) ;
// for ( size _ t i = 0 ; i < entryCount ; i + + ) {
// ssize _ t index = mEntries . indexOfKey ( other . mEntries . keyAt ( i ) ) ;
// if ( index < 0 ) {
// mEntries . add ( other . mEntries . keyAt ( i ) , other . mEntries [ i ] ) ;
// } else {
// if ( other . mEntries [ i ] ! = mEntries [ index ] ) {
// return UNKNOWN _ ERROR ;
for ( Entry < String , Byte > otherEntry : other . mEntries . entrySet ( ) ) { String key = otherEntry . getKey ( ) ; Byte curValue = mEntries . get ( key ) ; if ( curValue == null ) { mEntries . put ( key , otherEntry . getValue ( ) ) ; } else { if ( ! Objects . equals ( otherEntry . getValue ( ) , curValue ) ) { return UNKNOWN_ERROR ; } } } // Merge the lookup table . No entry can conflict
// ( value of 0 means not set ) .
for ( int i = 0 ; i < 256 ; i ++ ) { if ( mLookupTable [ i ] != other . mLookupTable [ i ] ) { if ( mLookupTable [ i ] == 0 ) { mLookupTable [ i ] = other . mLookupTable [ i ] ; } else if ( other . mLookupTable [ i ] != 0 ) { return UNKNOWN_ERROR ; } } } return NO_ERROR ;


signature:
public class DynamicRefTable { /** * the given package . */
int addMapping ( final String packageName , byte packageId ) { } }

implementation: Byte index = mEntries . get ( packageName ) ; if ( index == null ) { return UNKNOWN_ERROR ; } mLookupTable [ index ] = packageId ; return NO_ERROR ;


signature:
public class DynamicRefTable { /** * / / resource ID . */
int lookupResourceId ( Ref < Integer > resId ) { } }

implementation:
int res = resId . get ( ) ; int packageId = Res_GETPACKAGE ( res ) + 1 ; if ( packageId == APP_PACKAGE_ID && ! mAppAsLib ) { // No lookup needs to be done , app package IDs are absolute .
return NO_ERROR ; } if ( packageId == 0 || ( packageId == APP_PACKAGE_ID && mAppAsLib ) ) { // The package ID is 0x00 . That means that a shared library is accessing
// its own local resource .
// Or if app resource is loaded as shared library , the resource which has
// app package Id is local resources .
// so we fix up those resources with the calling package ID .
resId . set ( ( 0xFFFFFF & ( resId . get ( ) ) ) | ( ( ( int ) mAssignedPackageId ) << 24 ) ) ; return NO_ERROR ; } // Do a proper lookup .
int translatedId = mLookupTable [ packageId ] ; if ( translatedId == 0 ) { ALOGW ( "DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x." , mAssignedPackageId , packageId ) ; for ( int i = 0 ; i < 256 ; i ++ ) { if ( mLookupTable [ i ] != 0 ) { ALOGW ( "e[0x%02x] . 0x%02x" , i , mLookupTable [ i ] ) ; } } return UNKNOWN_ERROR ; } resId . set ( ( res & 0x00ffffff ) | ( ( ( int ) translatedId ) << 24 ) ) ; return NO_ERROR ;


signature:
public class ShadowContextWrapper { /** * Grant the given permissions for the given process and user . */
public void grantPermissions ( int pid , int uid , String ... permissions ) { } }

implementation: getShadowInstrumentation ( ) . grantPermissions ( pid , uid , permissions ) ;


signature:
public class ShadowContextWrapper { /** * Revoke the given permissions for the given process and user . */
public void denyPermissions ( int pid , int uid , String ... permissions ) { } }

implementation: getShadowInstrumentation ( ) . denyPermissions ( pid , uid , permissions ) ;


signature:
public class ShadowContextWrapper { /** * Makes { @ link Context # getSystemService ( String ) } return { @ code null } for the given system service
 * name , mimicking a device that doesn ' t have that system service . */
public void removeSystemService ( String name ) { } }

implementation: ( ( ShadowContextImpl ) Shadow . extract ( realContextWrapper . getBaseContext ( ) ) ) . removeSystemService ( name ) ;


signature:
public class DefaultSdkPicker { /** * Enumerate the SDKs to be used for this test .
 * @ param configuration a collection of configuration objects , including { @ link Config }
 * @ param usesSdk the { @ link UsesSdk } for the test
 * @ return the list of candidate { @ link Sdk } s .
 * @ since 3.9 */
@ Override @ Nonnull public List < Sdk > selectSdks ( Configuration configuration , UsesSdk usesSdk ) { } }

implementation: Config config = configuration . get ( Config . class ) ; Set < Sdk > sdks = new TreeSet < > ( configuredSdks ( config , usesSdk ) ) ; if ( enabledSdks != null ) { sdks = Sets . intersection ( sdks , enabledSdks ) ; } return Lists . newArrayList ( sdks ) ;


signature:
public class SupportFragmentController { /** * Sets up the given fragment by attaching it to an activity , calling its onCreate ( ) through
 * onResume ( ) lifecycle methods , and then making it visible . Note that the fragment will be added
 * to the view with ID 1. */
public static < F extends Fragment > F setupFragment ( F fragment ) { } }

implementation: return SupportFragmentController . of ( fragment ) . create ( ) . start ( ) . resume ( ) . visible ( ) . get ( ) ;


signature:
public class SupportFragmentController { /** * Sets up the given fragment by attaching it to an activity , calling its onCreate ( ) through
 * onResume ( ) lifecycle methods , and then making it visible . Note that the fragment will be added
 * to the view with ID 1. */
public static < F extends Fragment > F setupFragment ( F fragment , Class < ? extends FragmentActivity > fragmentActivityClass ) { } }

implementation: return SupportFragmentController . of ( fragment , fragmentActivityClass ) . create ( ) . start ( ) . resume ( ) . visible ( ) . get ( ) ;


signature:
public class SupportFragmentController { /** * Creates the activity with { @ link Bundle } and adds the fragment to the view with ID
 * { @ code contentViewId } . */
public SupportFragmentController < F > create ( final int contentViewId , final Bundle bundle ) { } }

implementation: shadowMainLooper . runPaused ( new Runnable ( ) { @ Override public void run ( ) { activityController . create ( bundle ) . get ( ) . getSupportFragmentManager ( ) . beginTransaction ( ) . add ( contentViewId , fragment ) . commitNow ( ) ; } } ) ; return this ;


signature:
public class ShadowLegacyAssetManager { /** * Extract an asset from a zipped up assets provided by the build system , this is required because
 * there is no way to get a FileDescriptor from a zip entry . This is a temporary measure for Bazel
 * which can be removed once binary resources are supported . */
private static Path getFileFromZip ( Path path ) { } }

implementation: byte [ ] buffer = new byte [ 1024 ] ; try { Path outputDir = new TempDirectory ( "robolectric_assets" ) . create ( "fromzip" ) ; try ( InputStream zis = Fs . getInputStream ( path ) ) { Path fileFromZip = outputDir . resolve ( path . getFileName ( ) . toString ( ) ) ; try ( OutputStream fos = Files . newOutputStream ( fileFromZip ) ) { int len ; while ( ( len = zis . read ( buffer ) ) > 0 ) { fos . write ( buffer , 0 , len ) ; } } return fileFromZip ; } } catch ( IOException e ) { throw new RuntimeException ( e ) ; }


signature:
public class ShadowLegacyAssetManager { /** * todo : DRY up # resolveResource vs # resolveResourceValue */
private ResName resolveResource ( TypedResource value , ResTable_config config , ResName resName ) { } }

implementation: while ( value != null && value . isReference ( ) ) { String s = value . asString ( ) ; if ( AttributeResource . isNull ( s ) || AttributeResource . isEmpty ( s ) ) { value = null ; } else { String refStr = s . substring ( 1 ) . replace ( "+" , "" ) ; resName = ResName . qualifyResName ( refStr , resName ) ; value = resourceTable . getValue ( resName , config ) ; } } return resName ;


signature:
public class ShadowLegacyAssetManager { /** * jint offset , jint len ) { */
@ Implementation ( minSdk = P ) protected static int nativeAssetRead ( long asset_ptr , byte [ ] java_buffer , int offset , int len ) throws IOException { } }

implementation: return ShadowArscAssetManager9 . nativeAssetRead ( asset_ptr , java_buffer , offset , len ) ;


signature:
public class ShadowLegacyAssetManager { /** * jint whence ) { */
@ Implementation ( minSdk = P ) protected static long nativeAssetSeek ( long asset_ptr , long offset , int whence ) { } }

implementation: return ShadowArscAssetManager9 . nativeAssetSeek ( asset_ptr , offset , whence ) ;


signature:
public class FakeHttp { /** * Sets up an HTTP response to be returned by calls to Apache ' s { @ code HttpClient } implementers .
 * @ param statusCode the status code of the response
 * @ param responseBody the body of the response
 * @ param headers optional headers for the request */
public static void addPendingHttpResponse ( int statusCode , String responseBody , Header ... headers ) { } }

implementation: getFakeHttpLayer ( ) . addPendingHttpResponse ( statusCode , responseBody , headers ) ;


signature:
public class FakeHttp { /** * Sets up an HTTP response to be returned by calls to Apache ' s { @ code HttpClient } implementers .
 * @ param statusCode the status code of the response
 * @ param responseBody the body of the response
 * @ param contentType the contentType of the response
 * @ deprecated use { @ link # addPendingHttpResponse ( int , String , org . apache . http . Header . . . ) } instead */
@ Deprecated public static void addPendingHttpResponseWithContentType ( int statusCode , String responseBody , Header contentType ) { } }

implementation: getFakeHttpLayer ( ) . addPendingHttpResponse ( statusCode , responseBody , contentType ) ;


signature:
public class FakeHttp { /** * Accessor to obtain HTTP requests made during the current test in the order in which they were made .
 * @ return the requested request or null if there are none . */
public static HttpRequest getNextSentHttpRequest ( ) { } }

implementation: HttpRequestInfo httpRequestInfo = getFakeHttpLayer ( ) . getNextSentHttpRequestInfo ( ) ; return httpRequestInfo == null ? null : httpRequestInfo . getHttpRequest ( ) ;


signature:
public class FakeHttp { /** * Adds an HTTP response rule . The response will be returned when the rule is matched .
 * @ param method method to match .
 * @ param uri uri to match .
 * @ param response response to return when a match is found . */
public static void addHttpResponseRule ( String method , String uri , HttpResponse response ) { } }

implementation: getFakeHttpLayer ( ) . addHttpResponseRule ( method , uri , response ) ;


signature:
public class FakeHttp { /** * Adds an HTTP response rule . For each time the rule is matched , responses will be shifted
 * off the list and returned . When all responses have been given and the rule is matched again ,
 * an exception will be thrown .
 * @ param requestMatcher custom { @ code RequestMatcher } .
 * @ param responses responses to return in order when a match is found . */
public static void addHttpResponseRule ( RequestMatcher requestMatcher , List < ? extends HttpResponse > responses ) { } }

implementation: getFakeHttpLayer ( ) . addHttpResponseRule ( requestMatcher , responses ) ;


signature:
public class ShadowMediaMuxer { /** * Generates and returns an internal id to track the FileOutputStream corresponding to individual
 * MediaMuxer instances . */
@ Implementation protected static long nativeSetup ( @ NonNull FileDescriptor fd , int format ) throws IOException { } }

implementation: FileOutputStream outputStream = fdToStream . get ( fd ) ; long potentialKey ; do { potentialKey = random . nextLong ( ) ; } while ( potentialKey == 0 || outputStreams . putIfAbsent ( potentialKey , outputStream ) != null ) ; nextTrackIndices . put ( potentialKey , new AtomicInteger ( 0 ) ) ; return potentialKey ;


signature:
public class ShadowMediaMuxer { /** * Returns an incremented track id for the associated muxer . */
@ Implementation protected static int nativeAddTrack ( long nativeObject , @ NonNull String [ ] keys , @ NonNull Object [ ] values ) { } }

implementation: AtomicInteger nextTrackIndex = nextTrackIndices . get ( nativeObject ) ; if ( nextTrackIndex == null ) { throw new IllegalStateException ( "No next track index configured for key: " + nativeObject ) ; } return nextTrackIndex . getAndIncrement ( ) ;


signature:
public class ShadowMediaMuxer { /** * Writes the given data to the FileOutputStream for the associated muxer . */
@ Implementation protected static void nativeWriteSampleData ( long nativeObject , int trackIndex , @ NonNull ByteBuffer byteBuf , int offset , int size , long presentationTimeUs , @ MediaCodec . BufferFlag int flags ) { } }

implementation: int toWrite = size - offset ; byte [ ] bytes = new byte [ toWrite ] ; byteBuf . get ( bytes , 0 , toWrite ) ; try { getStream ( nativeObject ) . write ( bytes ) ; } catch ( IOException e ) { throw new RuntimeException ( "Unable to write to temporary file." , e ) ; }


signature:
public class ShadowMediaMuxer { /** * Closes the FileOutputStream for the associated muxer . */
@ Implementation protected static void nativeStop ( long nativeObject ) { } }

implementation:
try { // Close the output stream .
getStream ( nativeObject ) . close ( ) ; // Clear the stream from both internal caches .
fdToStream . remove ( outputStreams . remove ( nativeObject ) . getFD ( ) ) ; } catch ( IOException e ) { throw new RuntimeException ( "Unable to close temporary file." , e ) ; }


signature:
public class FakeHttpLayer { /** * Add a response rule .
 * @ param requestMatcher Request matcher
 * @ param responses A list of responses that are returned to matching requests in order from first to last . */
public void addHttpResponseRule ( RequestMatcher requestMatcher , List < ? extends HttpResponse > responses ) { } }

implementation: addHttpResponseRule ( new RequestMatcherResponseRule ( requestMatcher , responses ) ) ;


signature:
public class ShadowMediaRouter { /** * Adds the Bluetooth A2DP route and ensures it ' s the selected route , simulating connecting a
 * Bluetooth device . */
public void addBluetoothRoute ( ) { } }

implementation: updateBluetoothAudioRoute ( BLUETOOTH_DEVICE_NAME ) ; if ( RuntimeEnvironment . getApiLevel ( ) <= JELLY_BEAN_MR1 ) { ReflectionHelpers . callInstanceMethod ( MediaRouter . class , realObject , "selectRouteInt" , ClassParameter . from ( int . class , MediaRouter . ROUTE_TYPE_LIVE_AUDIO ) , ClassParameter . from ( RouteInfo . class , getBluetoothA2dpRoute ( ) ) ) ; } else { realObject . selectRoute ( MediaRouter . ROUTE_TYPE_LIVE_AUDIO , getBluetoothA2dpRoute ( ) ) ; }


signature:
public class ShadowMediaRouter { /** * Creates a new { @ link AudioRoutesInfo } to be used for updating the Bluetooth audio route .
 * @ param bluetoothDeviceName the name of the Bluetooth device or null to indicate that the
 * already - existing Bluetooth A2DP device should be removed */
private static AudioRoutesInfo newAudioRouteInfo ( @ Nullable String bluetoothDeviceName ) { } }

implementation:
Parcel p = Parcel . obtain ( ) ; TextUtils . writeToParcel ( bluetoothDeviceName , p , /* parcelableFlags = */
0 ) ; p . setDataPosition ( 0 ) ; return AudioRoutesInfo . CREATOR . createFromParcel ( p ) ;


signature:
public class ShadowProcess { /** * Stores priority for the given thread , but doesn ' t actually change it to not mess up with test
 * runner . Unlike real implementation does not throw any exceptions .
 * @ param tid The identifier of the thread . If equals zero , the identifier of the calling thread
 * will be used . */
@ Implementation protected static final void setThreadPriority ( int tid , int priority ) { } }

implementation: checkArgument ( priority >= android . os . Process . THREAD_PRIORITY_URGENT_AUDIO && priority <= android . os . Process . THREAD_PRIORITY_LOWEST , "priority %s out of range. Use a Process.THREAD_PRIORITY_* constant." , priority ) ; if ( tid == 0 ) { tid = ShadowProcess . myTid ( ) ; } synchronized ( threadPrioritiesLock ) { threadPriorities . put ( tid , priority ) ; }


signature:
public class ShadowProcess { /** * Returns priority stored for the given thread .
 * @ param tid The identifier of the thread . If equals zero , the identifier of the calling thread
 * will be used . */
@ Implementation protected static final int getThreadPriority ( int tid ) { } }

implementation: if ( tid == 0 ) { tid = ShadowProcess . myTid ( ) ; } synchronized ( threadPrioritiesLock ) { return threadPriorities . getOrDefault ( tid , 0 ) ; }


signature:
public class NativeBitSet64 { /** * Gets the index of the specified bit in the set , which is the number of marked bits that appear
 * before the specified bit . */
int getIndexOfBit ( int n ) { } }

implementation:
// return _ _ builtin _ popcountll ( value & ~ ( 0xfffffULL > > n ) ) ;
int numMarkedBits = 0 ; for ( int i = 0 ; i < n ; i ++ ) { if ( hasBit ( i ) ) { numMarkedBits ++ ; } } return numMarkedBits ;


signature:
public class ShadowAppOpsManager { /** * Change the operating mode for the given op in the given app package . You must pass in both the
 * uid and name of the application whose mode is being modified ; if these do not match , the
 * modification will not be applied .
 * < p > This method is public for testing { @ link # checkOpNoThrow } . If { @ link # checkOpNoThrow } is
 * called afterwards with the { @ code op } , { @ code ui } , and { @ code packageName } provided , it will
 * return the { @ code mode } set here .
 * @ param op The operation to modify . One of the OPSTR _ * constants .
 * @ param uid The user id of the application whose mode will be changed .
 * @ param packageName The name of the application package name whose mode will be changed . */
@ Implementation ( minSdk = P ) @ HiddenApi @ SystemApi @ RequiresPermission ( android . Manifest . permission . MANAGE_APP_OPS_MODES ) public void setMode ( String op , int uid , String packageName , int mode ) { } }

implementation: setMode ( AppOpsManager . strOpToOp ( op ) , uid , packageName , mode ) ;


signature:
public class ShadowAppOpsManager { /** * Int version of { @ link # setMode ( String , int , String , int ) } .
 * < p > This method is public for testing { @ link # checkOpNoThrow } . If { @ link # checkOpNoThrow } is *
 * called afterwards with the { @ code op } , { @ code ui } , and { @ code packageName } provided , it will *
 * return the { @ code mode } set here . */
@ Implementation ( minSdk = KITKAT ) @ HiddenApi @ RequiresPermission ( android . Manifest . permission . MANAGE_APP_OPS_MODES ) public void setMode ( int op , int uid , String packageName , int mode ) { } }

implementation: Integer oldMode = appModeMap . put ( getOpMapKey ( uid , packageName , op ) , mode ) ; OnOpChangedListener listener = appOpListeners . get ( getListenerKey ( op , packageName ) ) ; if ( listener != null && ! Objects . equals ( oldMode , mode ) ) { String [ ] sOpToString = ReflectionHelpers . getStaticField ( AppOpsManager . class , "sOpToString" ) ; listener . onOpChanged ( sOpToString [ op ] , packageName ) ; }


signature:
public class ShadowAppOpsManager { /** * Like { @ link AppOpsManager # checkOp } but instead of throwing a { @ link SecurityException } it
 * returns { @ link AppOpsManager # MODE _ ERRORED } .
 * < p > Made public for testing { @ link # setMode } as the method is { @ coe @ hide } . */
@ Implementation ( minSdk = KITKAT ) @ HiddenApi public int checkOpNoThrow ( int op , int uid , String packageName ) { } }

implementation: Integer mode = appModeMap . get ( getOpMapKey ( uid , packageName , op ) ) ; if ( mode == null ) { return AppOpsManager . MODE_ALLOWED ; } return mode ;


signature:
public class ShadowAppOpsManager { /** * Sets audio restrictions .
 * < p > This method is public for testing , as the original method is { @ code @ hide } . */
@ Implementation ( minSdk = LOLLIPOP ) @ HiddenApi public void setRestriction ( int code , @ AttributeUsage int usage , int mode , String [ ] exceptionPackages ) { } }

implementation: audioRestrictions . put ( getAudioRestrictionKey ( code , usage ) , new ModeAndException ( mode , exceptionPackages ) ) ;


signature:
public class ShadowLegacyMessage { /** * Hook to unscheduled the callback when the message is recycled .
 * Invokes { @ link # unschedule ( ) } and then calls through to the
 * package private method { @ link Message # recycleUnchecked ( ) }
 * on the real object . */
@ HiddenApi @ Implementation ( minSdk = LOLLIPOP ) public void recycleUnchecked ( ) { } }

implementation:
if ( getApiLevel ( ) >= LOLLIPOP ) { unschedule ( ) ; directlyOn ( realMessage , Message . class , "recycleUnchecked" ) ; } else { // provide forward compatibility with SDK 21.
recycle ( ) ; }


signature:
public class ShadowArscApkAssets9 { /** * Necessary to shadow this method because the framework path is hard - coded .
 * Called from AssetManager . createSystemAssetsInZygoteLocked ( ) in P + . */
@ Implementation protected static ApkAssets loadFromPath ( String path , boolean system ) throws IOException { } }

implementation: System . out . println ( "Called loadFromPath(" + path + ", " + system + "); mode=" + ( RuntimeEnvironment . useLegacyResources ( ) ? "legacy" : "binary" ) + " sdk=" + RuntimeEnvironment . getApiLevel ( ) ) ; if ( FRAMEWORK_APK_PATH . equals ( path ) ) { path = RuntimeEnvironment . getAndroidFrameworkJarPath ( ) . toString ( ) ; } String finalPath = path ; return getFromCacheOrLoad ( new Key ( null , path , system , false , false ) , ( ) -> directlyOn ( ApkAssets . class , "loadFromPath" , ClassParameter . from ( String . class , finalPath ) , ClassParameter . from ( boolean . class , system ) ) ) ;


signature:
public class ShadowArscApkAssets9 { /** * jboolean force _ shared _ lib , jboolean overlay ) { */
@ Implementation protected static long nativeLoad ( String java_path , boolean system , boolean force_shared_lib , boolean overlay ) throws IOException { } }

implementation: String path = java_path ; if ( path == null ) { return 0 ; } ATRACE_NAME ( String . format ( "LoadApkAssets(%s)" , path ) ) ; CppApkAssets apk_assets ; try { if ( overlay ) { apk_assets = CppApkAssets . LoadOverlay ( path , system ) ; } else if ( force_shared_lib ) { apk_assets = CppApkAssets . LoadAsSharedLibrary ( path , system ) ; } else { apk_assets = CppApkAssets . Load ( path , system ) ; } } catch ( OutOfMemoryError e ) { OutOfMemoryError outOfMemoryError = new OutOfMemoryError ( "Failed to load " + path ) ; outOfMemoryError . initCause ( e ) ; throw outOfMemoryError ; } if ( apk_assets == null ) { String error_msg = String . format ( "Failed to load asset path %s" , path ) ; throw new IOException ( error_msg ) ; } return Registries . NATIVE_APK_ASSETS_REGISTRY . register ( apk_assets ) ;


signature:
public class ShadowArscApkAssets9 { /** * jstring friendly _ name , jboolean system , jboolean force _ shared _ lib ) { */
@ Implementation protected static long nativeLoadFromFd ( FileDescriptor file_descriptor , String friendly_name , boolean system , boolean force_shared_lib ) { } }

implementation:
String friendly_name_utf8 = friendly_name ; if ( friendly_name_utf8 == null ) { return 0 ; } throw new UnsupportedOperationException ( ) ; // ATRACE _ NAME ( String . format ( " LoadApkAssetsFd ( % s ) " , friendly _ name _ utf8 ) ) ;
// int fd = jniGetFDFromFileDescriptor ( env , file _ descriptor ) ;
// if ( fd < 0 ) {
// throw new IllegalArgumentException ( " Bad FileDescriptor " ) ;
// unique _ fd dup _ fd ( . dup ( fd ) ) ;
// if ( dup _ fd < 0 ) {
// throw new IOException ( errno ) ;
// return 0;
// ApkAssets apk _ assets = ApkAssets . LoadFromFd ( std . move ( dup _ fd ) ,
// friendly _ name _ utf8,
// system , force _ shared _ lib ) ;
// if ( apk _ assets = = null ) {
// String error _ msg = String . format ( " Failed to load asset path % s from fd % d " ,
// friendly _ name _ utf8 , dup _ fd . get ( ) ) ;
// throw new IOException ( error _ msg ) ;
// return 0;
// return ShadowArscAssetManager9 . NATIVE _ APK _ ASSETS _ REGISTRY . getNativeObjectId ( apk _ assets ) ;


signature:
public class ShadowArscApkAssets9 { /** * static jstring NativeGetAssetPath ( JNIEnv * env , jclass / * clazz */
, jlong ptr ) { } }

implementation: * / @ Implementation protected static String nativeGetAssetPath ( long ptr ) { CppApkAssets apk_assets = Registries . NATIVE_APK_ASSETS_REGISTRY . getNativeObject ( ptr ) ; return apk_assets . GetPath ( ) ;


signature:
public class ShadowArscApkAssets9 { /** * static jlong NativeGetStringBlock ( JNIEnv * / * env */
, jclass /* clazz */
, jlong ptr ) { } }

implementation: * / @ Implementation protected static long nativeGetStringBlock ( long ptr ) { CppApkAssets apk_assets = Registries . NATIVE_APK_ASSETS_REGISTRY . getNativeObject ( ptr ) ; return apk_assets . GetLoadedArsc ( ) . GetStringPool ( ) . getNativePtr ( ) ;


signature:
public class ShadowArscApkAssets9 { /** * static jboolean NativeIsUpToDate ( JNIEnv * / * env */
, jclass /* clazz */
, jlong ptr ) { } }

implementation:
* / @ Implementation protected static boolean nativeIsUpToDate ( long ptr ) { CppApkAssets apk_assets = Registries . NATIVE_APK_ASSETS_REGISTRY . getNativeObject ( ptr ) ; // ( void ) apk _ assets ;
return JNI_TRUE ;


signature:
public class ShadowArscApkAssets9 { /** * static jlong NativeOpenXml ( JNIEnv * env , jclass / * clazz */
, jlong ptr , jstring file_name ) { } }

implementation:
* / @ Implementation protected static long nativeOpenXml ( long ptr , String file_name ) throws FileNotFoundException { String path_utf8 = file_name ; if ( path_utf8 == null ) { return 0 ; } CppApkAssets apk_assets = Registries . NATIVE_APK_ASSETS_REGISTRY . getNativeObject ( ptr ) ; Asset asset = apk_assets . Open ( path_utf8 , Asset . AccessMode . ACCESS_RANDOM ) ; if ( asset == null ) { throw new FileNotFoundException ( path_utf8 ) ; } // DynamicRefTable is only needed when looking up resource references . Opening an XML file
// directly from an ApkAssets has no notion of proper resource references .
ResXMLTree xml_tree = new ResXMLTree ( null ) ; // util . make _ unique < ResXMLTree > ( nullptr / * dynamicRefTable * / ) ;
int err = xml_tree . setTo ( asset . getBuffer ( true ) , ( int ) asset . getLength ( ) , true ) ; // asset . reset ( ) ;
if ( err != NO_ERROR ) { throw new FileNotFoundException ( "Corrupt XML binary file" ) ; } return Registries . NATIVE_RES_XML_TREES . register ( xml_tree ) ; // reinterpret _ cast < jlong > ( xml _ tree . release ( ) ) ;


signature:
public class ShadowAppTask { /** * Starts the activity using given context . Started activity can be checked using { @ link
 * ShadowContextWrapper # getNextStartedActivity ( ) }
 * @ param context Context with which the activity will be start .
 * @ param intent Intent of the activity to be started .
 * @ param options Extras passed to the activity . */
@ Implementation protected void startActivity ( Context context , Intent intent , Bundle options ) { } }

implementation: context . startActivity ( intent , options ) ;


signature:
public class ResourceHelper { /** * Returns the color value represented by the given string value
 * @ param value the color value
 * @ return the color as an int
 * @ throws NumberFormatException if the conversion failed . */
public static int getColor ( String value ) { } }

implementation:
if ( value != null ) { if ( value . startsWith ( "#" ) == false ) { throw new NumberFormatException ( String . format ( "Color value '%s' must start with #" , value ) ) ; } value = value . substring ( 1 ) ; // make sure it ' s not longer than 32bit
if ( value . length ( ) > 8 ) { throw new NumberFormatException ( String . format ( "Color value '%s' is too long. Format is either" + "#AARRGGBB, #RRGGBB, #RGB, or #ARGB" , value ) ) ; } if ( value . length ( ) == 3 ) { // RGB format
char [ ] color = new char [ 8 ] ; color [ 0 ] = color [ 1 ] = 'F' ; color [ 2 ] = color [ 3 ] = value . charAt ( 0 ) ; color [ 4 ] = color [ 5 ] = value . charAt ( 1 ) ; color [ 6 ] = color [ 7 ] = value . charAt ( 2 ) ; value = new String ( color ) ; } else if ( value . length ( ) == 4 ) { // ARGB format
char [ ] color = new char [ 8 ] ; color [ 0 ] = color [ 1 ] = value . charAt ( 0 ) ; color [ 2 ] = color [ 3 ] = value . charAt ( 1 ) ; color [ 4 ] = color [ 5 ] = value . charAt ( 2 ) ; color [ 6 ] = color [ 7 ] = value . charAt ( 3 ) ; value = new String ( color ) ; } else if ( value . length ( ) == 6 ) { value = "FF" + value ; } // this is a RRGGBB or AARRGGBB value
// Integer . parseInt will fail to inferFromValue strings like " ff191919 " , so we use
// a Long , but cast the result back into an int , since we know that we ' re only
// dealing with 32 bit values .
return ( int ) Long . parseLong ( value , 16 ) ; } throw new NumberFormatException ( ) ;


signature:
public class ResourceHelper { /** * Returns the TypedValue color type represented by the given string value
 * @ param value the color value
 * @ return the color as an int . For backwards compatibility , will return a default of ARGB8 if
 * value format is unrecognized . */
public static int getColorType ( String value ) { } }

implementation: if ( value != null && value . startsWith ( "#" ) ) { switch ( value . length ( ) ) { case 4 : return TypedValue . TYPE_INT_COLOR_RGB4 ; case 5 : return TypedValue . TYPE_INT_COLOR_ARGB4 ; case 7 : return TypedValue . TYPE_INT_COLOR_RGB8 ; case 9 : return TypedValue . TYPE_INT_COLOR_ARGB8 ; } } return TypedValue . TYPE_INT_COLOR_ARGB8 ;


signature:
public class ResourceHelper { /** * Parse a float attribute and return the parsed value into a given TypedValue .
 * @ param attribute the name of the attribute . Can be null if < var > requireUnit < / var > is false .
 * @ param value the string value of the attribute
 * @ param outValue the TypedValue to receive the parsed value
 * @ param requireUnit whether the value is expected to contain a unit .
 * @ return true if success . */
public static boolean parseFloatAttribute ( String attribute , String value , TypedValue outValue , boolean requireUnit ) { } }

implementation:
assert requireUnit == false || attribute != null ; // remove the space before and after
value = value . trim ( ) ; int len = value . length ( ) ; if ( len <= 0 ) { return false ; } // check that there ' s no non ascii characters .
char [ ] buf = value . toCharArray ( ) ; for ( int i = 0 ; i < len ; i ++ ) { if ( buf [ i ] > 255 ) { return false ; } } // check the first character
if ( buf [ 0 ] < '0' && buf [ 0 ] > '9' && buf [ 0 ] != '.' && buf [ 0 ] != '-' ) { return false ; } // now look for the string that is after the float . . .
Matcher m = sFloatPattern . matcher ( value ) ; if ( m . matches ( ) ) { String f_str = m . group ( 1 ) ; String end = m . group ( 2 ) ; float f ; try { f = Float . parseFloat ( f_str ) ; } catch ( NumberFormatException e ) { // this shouldn ' t happen with the regexp above .
return false ; } if ( end . length ( ) > 0 && end . charAt ( 0 ) != ' ' ) { // Might be a unit . . .
if ( parseUnit ( end , outValue , sFloatOut ) ) { computeTypedValue ( outValue , f , sFloatOut [ 0 ] ) ; return true ; } return false ; } // make sure it ' s only spaces at the end .
end = end . trim ( ) ; if ( end . length ( ) == 0 ) { if ( outValue != null ) { outValue . assetCookie = 0 ; outValue . string = null ; if ( requireUnit == false ) { outValue . type = TypedValue . TYPE_FLOAT ; outValue . data = Float . floatToIntBits ( f ) ; } else { // no unit when required ? Use dp and out an error .
applyUnit ( sUnitNames [ 1 ] , outValue , sFloatOut ) ; computeTypedValue ( outValue , f , sFloatOut [ 0 ] ) ; System . out . println ( String . format ( "Dimension \"%1$s\" in attribute \"%2$s\" is missing unit!" , value , attribute ) ) ; } return true ; } } } return false ;


signature:
public class ShadowImageDecoder { /** * native method implementations . . . */
@ Implementation protected static ImageDecoder nCreate ( long asset , Source source ) throws IOException { } }

implementation: return ImageDecoder_nCreateAsset ( asset , source ) ;


signature:
public class ShadowImageDecoder { /** * The fd must be seekable . */
@ Implementation protected static ImageDecoder nCreate ( FileDescriptor fd , Source src ) throws IOException { } }

implementation: return ImageDecoder_nCreateFd ( fd , src ) ;


signature:
public class DirBaseNameFilter { /** * It sure seems like a bug that Path # getFileName ( ) returns " name / " for paths inside a jar , but
 * " name " for paths on a regular filesystem . It ' s always a normal slash , even on Windows . : - p */
private String nameWithoutTrailingSeparator ( Path file ) { } }

implementation: String fileName = file . getFileName ( ) . toString ( ) ; int trailingSlash = fileName . indexOf ( '/' ) ; if ( trailingSlash != - 1 ) { fileName = fileName . substring ( 0 , trailingSlash ) ; } return fileName ;


signature:
public class ShadowActivity { /** * Constructs a new Window ( a { @ link com . android . internal . policy . impl . PhoneWindow } ) if no window
 * has previously been set .
 * @ return the window associated with this Activity */
@ Implementation protected Window getWindow ( ) { } }

implementation: Window window = directlyOn ( realActivity , Activity . class ) . getWindow ( ) ; if ( window == null ) { try { window = ShadowWindow . create ( realActivity ) ; setWindow ( window ) ; } catch ( Exception e ) { throw new RuntimeException ( "Window creation failed!" , e ) ; } } return window ;


signature:
public class ShadowActivity { /** * Consumes and returns the next { @ code Intent } on the
 * started activities for results stack .
 * @ return the next started { @ code Intent } for an activity , wrapped in
 * an { @ link ShadowActivity . IntentForResult } object */
public IntentForResult getNextStartedActivityForResult ( ) { } }

implementation: ActivityThread activityThread = ( ActivityThread ) RuntimeEnvironment . getActivityThread ( ) ; ShadowInstrumentation shadowInstrumentation = Shadow . extract ( activityThread . getInstrumentation ( ) ) ; return shadowInstrumentation . getNextStartedActivityForResult ( ) ;


signature:
public class ShadowActivity { /** * Perform a click on a menu item .
 * @ param menuItemResId Menu item resource ID .
 * @ return True if the click was handled , false otherwise . */
public boolean clickMenuItem ( int menuItemResId ) { } }

implementation: final RoboMenuItem item = new RoboMenuItem ( menuItemResId ) ; return realActivity . onMenuItemSelected ( Window . FEATURE_OPTIONS_PANEL , item ) ;


signature:
public class ShadowActivity { /** * For internal use only . Not for public use . */
public void callOnActivityResult ( int requestCode , int resultCode , Intent resultData ) { } }

implementation: final ActivityInvoker invoker = new ActivityInvoker ( ) ; invoker . call ( "onActivityResult" , Integer . TYPE , Integer . TYPE , Intent . class ) . with ( requestCode , resultCode , resultData ) ;


signature:
public class ShadowActivity { /** * Starts a lock task .
 * < p > The status of the lock task can be verified using { @ link # isLockTask } method . Otherwise this
 * implementation has no effect . */
@ Implementation ( minSdk = LOLLIPOP ) protected void startLockTask ( ) { } }

implementation: Shadow . < ShadowActivityManager > extract ( getActivityManager ( ) ) . setLockTaskModeState ( ActivityManager . LOCK_TASK_MODE_LOCKED ) ;


signature:
public class ShadowActivity { /** * Stops a lock task .
 * < p > The status of the lock task can be verified using { @ link # isLockTask } method . Otherwise this
 * implementation has no effect . */
@ Implementation ( minSdk = LOLLIPOP ) protected void stopLockTask ( ) { } }

implementation: Shadow . < ShadowActivityManager > extract ( getActivityManager ( ) ) . setLockTaskModeState ( ActivityManager . LOCK_TASK_MODE_NONE ) ;


signature:
public class ShadowTimeZoneFinder { /** * Reads tzlookup . xml from the files bundled inside android - all JARs . We need to read the file
 * instead of passing in the path because the real implementation uses { @ link java . nio . file . Paths }
 * which doesn ' t support reading from JARs . */
public static String readTzlookup ( ) { } }

implementation:
StringBuilder stringBuilder = new StringBuilder ( ) ; InputStream is = null ; try { try { is = ShadowTimeZoneFinder . class . getResourceAsStream ( TZLOOKUP_PATH ) ; BufferedReader reader = new BufferedReader ( new InputStreamReader ( is , UTF_8 ) ) ; for ( String line ; ( line = reader . readLine ( ) ) != null ; ) { stringBuilder . append ( line ) ; } } finally { if ( is != null ) { is . close ( ) ; } } } catch ( IOException e ) { // ignore
} return stringBuilder . toString ( ) ;


signature:
public class AttributeSetBuilderImpl { /** * todo rename to setAttribute ( ) , or just set ( ) ? */
@ Override public AttributeSetBuilder addAttribute ( int resId , String value ) { } }

implementation: attrToValue . put ( resId , value ) ; return this ;


signature:
public class Scheduler { /** * Sets the current idling state of this < tt > Scheduler < / tt > . If transitioning to the
 * { @ link IdleState # UNPAUSED } state any tasks scheduled to be run at or before the current time
 * will be run , and if transitioning to the { @ link IdleState # CONSTANT _ IDLE } state all scheduled
 * tasks will be run and the clock advanced to the time of the last runnable .
 * @ param idleState The new idle state of this < tt > Scheduler < / tt > .
 * @ see # setIdleState ( IdleState )
 * @ see # isPaused ( ) */
public synchronized void setIdleState ( IdleState idleState ) { } }

implementation: this . idleState = idleState ; switch ( idleState ) { case UNPAUSED : advanceBy ( 0 ) ; break ; case CONSTANT_IDLE : advanceToLastPostedRunnable ( ) ; break ; default : }


signature:
public class Scheduler { /** * Add a runnable to the queue to be run after a delay . */
public synchronized void postDelayed ( Runnable runnable , long delay , TimeUnit unit ) { } }

implementation: long delayMillis = unit . toMillis ( delay ) ; if ( ( idleState != CONSTANT_IDLE && ( isPaused ( ) || delayMillis > 0 ) ) || Thread . currentThread ( ) != associatedThread ) { runnables . add ( new ScheduledRunnable ( runnable , currentTime + delayMillis ) ) ; } else { runOrQueueRunnable ( runnable , currentTime + delayMillis ) ; }


signature:
public class Scheduler { /** * Add a runnable to the head of the queue .
 * @ param runnable Runnable to add . */
public synchronized void postAtFrontOfQueue ( Runnable runnable ) { } }

implementation: if ( isPaused ( ) || Thread . currentThread ( ) != associatedThread ) { final long timeDisambiguator ; if ( runnables . isEmpty ( ) ) { timeDisambiguator = nextTimeDisambiguator ++ ; } else { timeDisambiguator = runnables . peek ( ) . timeDisambiguator - 1 ; } runnables . add ( new ScheduledRunnable ( runnable , 0 , timeDisambiguator ) ) ; } else { runOrQueueRunnable ( runnable , currentTime ) ; }


signature:
public class Scheduler { /** * Remove a runnable from the queue .
 * @ param runnable Runnable to remove . */
public synchronized void remove ( Runnable runnable ) { } }

implementation: Iterator < ScheduledRunnable > iterator = runnables . iterator ( ) ; while ( iterator . hasNext ( ) ) { if ( iterator . next ( ) . runnable == runnable ) { iterator . remove ( ) ; } }


signature:
public class Scheduler { /** * Run all runnables in the queue , and any additional runnables they schedule that are scheduled
 * before the latest scheduled runnable currently in the queue .
 * @ return True if a runnable was executed . */
public synchronized boolean advanceToLastPostedRunnable ( ) { } }

implementation: long currentMaxTime = currentTime ; for ( ScheduledRunnable scheduled : runnables ) { if ( currentMaxTime < scheduled . scheduledTime ) { currentMaxTime = scheduled . scheduledTime ; } } return advanceTo ( currentMaxTime ) ;


signature:
public class Scheduler { /** * Run all runnables that are scheduled to run in the next time interval .
 * @ return True if a runnable was executed . */
public synchronized boolean advanceBy ( long amount , TimeUnit unit ) { } }

implementation: long endingTime = currentTime + unit . toMillis ( amount ) ; return advanceTo ( endingTime ) ;


signature:
public class Scheduler { /** * Run all runnables that are scheduled before the endTime .
 * @ param endTime Future time .
 * @ return True if a runnable was executed . */
public synchronized boolean advanceTo ( long endTime ) { } }

implementation: if ( endTime < currentTime || runnables . isEmpty ( ) ) { currentTime = endTime ; return false ; } int runCount = 0 ; while ( nextTaskIsScheduledBefore ( endTime ) ) { runOneTask ( ) ; ++ runCount ; } currentTime = endTime ; return runCount > 0 ;


signature:
public class Scheduler { /** * Run the next runnable in the queue .
 * @ return True if a runnable was executed . */
public synchronized boolean runOneTask ( ) { } }

implementation: ScheduledRunnable postedRunnable = runnables . poll ( ) ; if ( postedRunnable != null ) { if ( postedRunnable . scheduledTime > currentTime ) { currentTime = postedRunnable . scheduledTime ; } postedRunnable . run ( ) ; return true ; } return false ;


signature:
public class ShadowContextImpl { /** * Returns the handle to a system - level service by name . If the service is not available in
 * Roboletric , or it is set to unavailable in { @ link ShadowServiceManager # setServiceAvailability } ,
 * { @ code null } will be returned . */
@ Implementation @ Nullable protected Object getSystemService ( String name ) { } }

implementation: if ( removedSystemServices . contains ( name ) ) { return null ; } if ( ! systemServices . containsKey ( name ) ) { return directlyOn ( realContextImpl , ShadowContextImpl . CLASS_NAME , "getSystemService" , ClassParameter . from ( String . class , name ) ) ; } return systemServices . get ( name ) ;


signature:
public class ShadowContextImpl { /** * Forwards the call to { @ link # sendBroadcast ( Intent , String ) } , disregarding { @ code user } param . */
@ Implementation ( minSdk = JELLY_BEAN_MR1 ) @ RequiresPermission ( android . Manifest . permission . INTERACT_ACROSS_USERS ) protected void sendBroadcastAsUser ( @ RequiresPermission Intent intent , UserHandle user , @ Nullable String receiverPermission ) { } }

implementation: sendBroadcast ( intent , receiverPermission ) ;


signature:
public class ShadowContextImpl { /** * Behaves as { @ link # sendOrderedBroadcast } and currently ignores userHandle . */
@ Implementation ( minSdk = KITKAT ) protected void sendOrderedBroadcastAsUser ( Intent intent , UserHandle userHandle , String receiverPermission , BroadcastReceiver resultReceiver , Handler scheduler , int initialCode , String initialData , Bundle initialExtras ) { } }

implementation: sendOrderedBroadcast ( intent , receiverPermission , resultReceiver , scheduler , initialCode , initialData , initialExtras ) ;


signature:
public class ShadowContextImpl { /** * Binds to a service but ignores the given UserHandle . */
@ Implementation ( minSdk = LOLLIPOP ) protected boolean bindServiceAsUser ( Intent intent , final ServiceConnection serviceConnection , int i , UserHandle userHandle ) { } }

implementation: return getShadowInstrumentation ( ) . bindService ( intent , serviceConnection , i ) ;


signature:
public class ShadowContextImpl { /** * Behaves as { @ link # startActivity } . The user parameter is ignored . */
@ Implementation ( minSdk = LOLLIPOP ) protected void startActivityAsUser ( Intent intent , Bundle options , UserHandle user ) { } }

implementation:
// TODO : Remove this once { @ link com . android . server . wmActivityTaskManagerService } is
// properly shadowed .
directlyOn ( realContextImpl , ShadowContextImpl . CLASS_NAME , "startActivity" , ClassParameter . from ( Intent . class , intent ) , ClassParameter . from ( Bundle . class , options ) ) ;


signature:
public class ShadowResolveInfo { /** * Creates a { @ link ResolveInfo } .
 * @ param displayName Display name .
 * @ param packageName Package name .
 * @ return Resolve info instance . */
public static ResolveInfo newResolveInfo ( String displayName , String packageName ) { } }

implementation: return newResolveInfo ( displayName , packageName , null ) ;


signature:
public class ShadowResolveInfo { /** * Creates a { @ link ResolveInfo } .
 * @ param displayName Display name .
 * @ param packageName Package name .
 * @ param activityName Activity name .
 * @ return Resolve info instance . */
public static ResolveInfo newResolveInfo ( String displayName , String packageName , String activityName ) { } }

implementation: ResolveInfo resInfo = new ResolveInfo ( ) ; ActivityInfo actInfo = new ActivityInfo ( ) ; actInfo . applicationInfo = new ApplicationInfo ( ) ; actInfo . packageName = packageName ; actInfo . applicationInfo . packageName = packageName ; actInfo . name = activityName ; resInfo . activityInfo = actInfo ; resInfo . nonLocalizedLabel = displayName ; return resInfo ;


signature:
public class ShadowResolveInfo { /** * Copies { @ link ResolveInfo } .
 * < p > Note that this is shallow copy as performed by the copy constructor existing in API 17. */
public static ResolveInfo newResolveInfo ( ResolveInfo orig ) { } }

implementation:
ResolveInfo copy ; if ( Build . VERSION . SDK_INT >= 17 ) { copy = new ResolveInfo ( orig ) ; } else { copy = new ResolveInfo ( ) ; copy . activityInfo = orig . activityInfo ; copy . serviceInfo = orig . serviceInfo ; copy . filter = orig . filter ; copy . priority = orig . priority ; copy . preferredOrder = orig . preferredOrder ; copy . match = orig . match ; copy . specificIndex = orig . specificIndex ; copy . labelRes = orig . labelRes ; copy . nonLocalizedLabel = orig . nonLocalizedLabel ; copy . icon = orig . icon ; copy . resolvePackageName = orig . resolvePackageName ; } // For some reason isDefault field is not copied by the copy constructor .
copy . isDefault = orig . isDefault ; return copy ;


signature:
public class ShadowPausedSystemClock { /** * Sets the current wall time .
 * < p > Currently does not perform any permission checks .
 * @ return false if specified time is less than current time . */
@ Implementation protected static boolean setCurrentTimeMillis ( long millis ) { } }

implementation: if ( currentTimeMillis > millis ) { return false ; } currentTimeMillis = millis ; for ( Listener listener : listeners ) { listener . clockUpdated ( currentTimeMillis ) ; } return true ;


signature:
public class ShadowPausedMessageQueue { /** * nativePollOnce */
@ Implementation ( minSdk = JELLY_BEAN_MR2 , maxSdk = LOLLIPOP_MR1 ) protected static void nativePollOnce ( Object ptr , Object timeoutMillis ) { } }

implementation: long ptrLong = getLong ( ptr ) ; nativeQueueRegistry . getNativeObject ( ptrLong ) . nativePollOnce ( ptrLong , ( int ) timeoutMillis ) ;


signature:
public class ShadowPausedMessageQueue { /** * nativeWake */
@ Implementation ( minSdk = JELLY_BEAN_MR2 , maxSdk = KITKAT ) protected static void nativeWake ( Object ptr ) { } }

implementation:
// JELLY _ BEAN _ MR2 has a bug where nativeWake can get called when pointer has already been
// destroyed . See here where nativeWake is called outside the synchronized block
// https : / / android . googlesource . com / platform / frameworks / base / + / refs / heads / jb - mr2 - release / core / java / android / os / MessageQueue . java # 239
// So check to see if native object exists first
ShadowPausedMessageQueue q = nativeQueueRegistry . peekNativeObject ( getLong ( ptr ) ) ; if ( q != null ) { q . nativeWake ( getInt ( ptr ) ) ; }


signature:
public class ShadowPausedMessageQueue { /** * Exposes the API23 + _ isIdle method to older platforms */
@ Implementation ( minSdk = 23 ) public boolean isIdle ( ) { } }

implementation:
if ( Build . VERSION . SDK_INT >= M ) { return directlyOn ( realQueue , MessageQueue . class ) . isIdle ( ) ; } else { ReflectorMessageQueue internalQueue = reflector ( ReflectorMessageQueue . class , realQueue ) ; // this is a copy of the implementation from P
synchronized ( realQueue ) { final long now = SystemClock . uptimeMillis ( ) ; Message headMsg = internalQueue . getMessages ( ) ; if ( headMsg == null ) { return true ; } long when = shadowOfMsg ( headMsg ) . getWhen ( ) ; return now < when ; } }


signature:
public class ShadowPausedMessageQueue { /** * so it should be package private */
@ Override public void reset ( ) { } }

implementation: ReflectorMessageQueue msgQueue = reflector ( ReflectorMessageQueue . class , realQueue ) ; msgQueue . setMessages ( null ) ; msgQueue . setIdleHandlers ( new ArrayList < > ( ) ) ; msgQueue . setNextBarrierToken ( 0 ) ;


signature:
public class Robolectric { /** * Creates a ActivityController for the given activity class .
 * < p > Consider using { @ link androidx . test . core . app . ActivityScenario } instead , which provides
 * higher - level , streamlined APIs to control the lifecycle and it works with instrumentation tests
 * too . */
public static < T extends Activity > ActivityController < T > buildActivity ( Class < T > activityClass ) { } }

implementation: return buildActivity ( activityClass , null ) ;


signature:
public class Robolectric { /** * Creates a ActivityController for the given activity class with the intent .
 * < p > Note : the activity class is not determined by the intent .
 * < p > Consider using { @ link androidx . test . core . app . ActivityScenario } instead , which provides
 * higher - level , streamlined APIs to control the lifecycle and it works with instrumentation tests
 * too . */
public static < T extends Activity > ActivityController < T > buildActivity ( Class < T > activityClass , Intent intent ) { } }

implementation: return ActivityController . of ( ReflectionHelpers . callConstructor ( activityClass ) , intent ) ;


signature:
public class Robolectric { /** * Simulates starting activity with the given class type and returns its reference .
 * < p > Use { @ link androidx . test . core . app . ActivityScenario } instead , which works with
 * instrumentation tests too .
 * @ deprecated use { @ link androidx . test . core . app . ActivityScenario } */
@ Deprecated public static < T extends Activity > T setupActivity ( Class < T > activityClass ) { } }

implementation: return buildActivity ( activityClass ) . setup ( ) . get ( ) ;


signature:
public class Robolectric { /** * Creates a FragmentController for the given fragment class .
 * < p > FragmentController provides low - level APIs to control its lifecycle . Please consider using
 * { @ link androidx . fragment . app . testing . FragmentScenario } instead , which provides higher level
 * APIs and works with instrumentation tests too .
 * @ deprecated Native Fragments have been deprecated in Android P . Android encourages developers
 * to use androidx fragments , to test these use FragmentScenario . */
@ Deprecated public static < T extends Fragment > FragmentController < T > buildFragment ( Class < T > fragmentClass ) { } }

implementation: return FragmentController . of ( ReflectionHelpers . callConstructor ( fragmentClass ) ) ;


signature:
public class Robolectric { /** * Allows for the programmatic creation of an { @ link AttributeSet } .
 * Useful for testing { @ link View } classes without the need for creating XML snippets . */
public static org . robolectric . android . AttributeSetBuilder buildAttributeSet ( ) { } }

implementation: if ( useLegacy ( ) ) { return new AttributeSetBuilderImpl ( new LegacyResourceResolver ( RuntimeEnvironment . application , RuntimeEnvironment . getCompileTimeResourceTable ( ) ) ) { } ; } else { return new AttributeSetBuilderImpl ( new ArscResourceResolver ( RuntimeEnvironment . application ) ) { } ; }


signature:
public class ShadowTextToSpeech { /** * Speaks the string using the specified queuing strategy and speech parameters .
 * @ param params The real implementation converts the hashmap into a bundle , but the bundle
 * argument is not used in the shadow implementation . */
@ Implementation protected int speak ( final String text , final int queueMode , final HashMap < String , String > params ) { } }

implementation: if ( RuntimeEnvironment . getApiLevel ( ) >= LOLLIPOP ) { return Shadow . directlyOn ( tts , TextToSpeech . class ) . speak ( text , queueMode , params ) ; } return speak ( text , queueMode , null , params == null ? null : params . get ( Engine . KEY_PARAM_UTTERANCE_ID ) ) ;


signature:
public class ShadowDisplayManagerGlobal { /** * Returns the ' natural ' dimensions of the default display . */
@ Implementation ( minSdk = O_MR1 ) public Point getStableDisplaySize ( ) throws RemoteException { } }

implementation: DisplayInfo defaultDisplayInfo = mDm . getDisplayInfo ( Display . DEFAULT_DISPLAY ) ; return new Point ( defaultDisplayInfo . getNaturalWidth ( ) , defaultDisplayInfo . getNaturalHeight ( ) ) ;


signature:
public class Fs { /** * Use this method instead of { @ link Paths # get ( String , String . . . ) } or { @ link Paths # get ( URI ) } .
 * < p > Supports " file : path " , " jar : file : jarfile . jar ! / path " , and plain old paths .
 * < p > For JAR files , automatically open and cache filesystems . */
public static Path fromUrl ( String urlString ) { } }

implementation: if ( urlString . startsWith ( "file:" ) || urlString . startsWith ( "jar:" ) ) { URL url ; try { url = new URL ( urlString ) ; } catch ( MalformedURLException e ) { throw new RuntimeException ( "Failed to resolve path from " + urlString , e ) ; } return fromUrl ( url ) ; } else { return Paths . get ( urlString ) ; }


signature:
public class Fs { /** * Isn ' t this what { @ link Paths # get ( URI ) } should do ? */
public static Path fromUrl ( URL url ) { } }

implementation: try { switch ( url . getProtocol ( ) ) { case "file" : return Paths . get ( url . toURI ( ) ) ; case "jar" : String [ ] parts = url . getPath ( ) . split ( "!" , 0 ) ; Path jarFile = Paths . get ( new URI ( parts [ 0 ] ) . toURL ( ) . getFile ( ) ) ; FileSystem fs = getJarFs ( jarFile ) ; return fs . getPath ( parts [ 1 ] . substring ( 1 ) ) ; default : throw new IllegalArgumentException ( "unsupported fs type for '" + url + "'" ) ; } } catch ( Exception e ) { throw new RuntimeException ( "Failed to resolve path from " + url , e ) ; }


signature:
public class Fs { /** * Returns a reference - counted Jar FileSystem , possibly one that was previously returned . */
private static FileSystem getJarFs ( Path jarFile ) throws IOException { } }

implementation: Path key = jarFile . toAbsolutePath ( ) ; synchronized ( ZIP_FILESYSTEMS ) { FsWrapper fs = ZIP_FILESYSTEMS . get ( key ) ; if ( fs == null ) { fs = new FsWrapper ( FileSystems . newFileSystem ( key , null ) , key ) ; fs . incrRefCount ( ) ; ZIP_FILESYSTEMS . put ( key , fs ) ; } else { fs . incrRefCount ( ) ; } return fs ; }


signature:
public class ShadowGeocoder { /** * Returns an empty list by default , or the last value set by { @ link # setFromLocation ( List ) }
 * ` latitude ` and ` longitude ` are ignored by this implementation , except to check that they are in
 * appropriate bounds . ` maxResults ` determines the
 * maximum number of addresses to return . */
@ Implementation protected List < Address > getFromLocation ( double latitude , double longitude , int maxResults ) throws IOException { } }

implementation: Preconditions . checkArgument ( - 90 <= latitude && latitude <= 90 , "Latitude must be between -90 and 90, got %s" , latitude ) ; Preconditions . checkArgument ( - 180 <= longitude && longitude <= 180 , "Longitude must be between -180 and 180, got %s" , longitude ) ; return fromLocation . subList ( 0 , Math . min ( maxResults , fromLocation . size ( ) ) ) ;


signature:
public class ShadowLog { /** * Returns ordered list of all log items for a specific tag .
 * @ param tag The tag to get logs for
 * @ return The list of log items for the tag or an empty list if no logs for that tag exist . */
public static List < LogItem > getLogsForTag ( String tag ) { } }

implementation: Queue < LogItem > logs = logsByTag . get ( tag ) ; return logs == null ? Collections . emptyList ( ) : new ArrayList < > ( logs ) ;


signature:
public class ShadowLocationManager { /** * Sets the value to return from { @ link # getBestProvider ( android . location . Criteria , boolean ) } for the given
 * { @ code provider }
 * @ param provider name of the provider who should be considered best
 * @ param enabled Enabled
 * @ param criteria List of criteria
 * @ throws Exception if provider is not known
 * @ return false If provider is not enabled but it is supposed to be set as the best enabled provider don ' t set it , otherwise true */
public boolean setBestProvider ( String provider , boolean enabled , List < Criteria > criteria ) throws Exception { } }

implementation:
if ( ! getAllProviders ( ) . contains ( provider ) ) { throw new IllegalStateException ( "Best provider is not a known provider" ) ; } // If provider is not enabled but it is supposed to be set as the best enabled provider don ' t set it .
for ( String prvdr : providersEnabled . keySet ( ) ) { if ( provider . equals ( prvdr ) && providersEnabled . get ( prvdr ) . enabled != enabled ) { return false ; } } if ( enabled ) { bestEnabledProvider = provider ; if ( provider . equals ( bestDisabledProvider ) ) { bestDisabledProvider = null ; } } else { bestDisabledProvider = provider ; if ( provider . equals ( bestEnabledProvider ) ) { bestEnabledProvider = null ; } } if ( criteria == null ) { return true ; } LocationProviderEntry entry ; if ( ! providersEnabled . containsKey ( provider ) ) { entry = new LocationProviderEntry ( ) ; entry . enabled = enabled ; entry . criteria = criteria ; } else { entry = providersEnabled . get ( provider ) ; } providersEnabled . put ( provider , entry ) ; return true ;


signature:
public class ShadowLocationManager { /** * Returns the distance between the two locations in meters .
 * Adapted from : http : / / stackoverflow . com / questions / 837872 / calculate - distance - in - meters - when - you - know - longitude - and - latitude - in - java */
private static float distanceBetween ( Location location1 , Location location2 ) { } }

implementation: double earthRadius = 3958.75 ; double latDifference = Math . toRadians ( location2 . getLatitude ( ) - location1 . getLatitude ( ) ) ; double lonDifference = Math . toRadians ( location2 . getLongitude ( ) - location1 . getLongitude ( ) ) ; double a = Math . sin ( latDifference / 2 ) * Math . sin ( latDifference / 2 ) + Math . cos ( Math . toRadians ( location1 . getLatitude ( ) ) ) * Math . cos ( Math . toRadians ( location2 . getLatitude ( ) ) ) * Math . sin ( lonDifference / 2 ) * Math . sin ( lonDifference / 2 ) ; double c = 2 * Math . atan2 ( Math . sqrt ( a ) , Math . sqrt ( 1 - a ) ) ; double dist = Math . abs ( earthRadius * c ) ; int meterConversion = 1609 ; return ( float ) ( dist * meterConversion ) ;


signature:
public class ShadowPathMeasure { /** * Note : This is not mathematically correct . */
@ Implementation protected boolean getPosTan ( float distance , float pos [ ] , float tan [ ] ) { } }

implementation:
if ( ( pos != null && pos . length < 2 ) || ( tan != null && tan . length < 2 ) ) { throw new ArrayIndexOutOfBoundsException ( ) ; } // This is not mathematically correct , but the simulation keeps the support library happy .
if ( getLength ( ) > 0 ) { pos [ 0 ] = round ( distance / getLength ( ) , 4 ) ; pos [ 1 ] = round ( distance / getLength ( ) , 4 ) ; } return true ;


signature:
public class ShadowActivityManager { /** * Returns information seeded by { @ link # setProcesses } . */
@ Implementation protected static void getMyMemoryState ( ActivityManager . RunningAppProcessInfo inState ) { } }

implementation: fillInProcessInfo ( inState ) ; for ( ActivityManager . RunningAppProcessInfo info : processes ) { if ( info . pid == Process . myPid ( ) ) { inState . importance = info . importance ; inState . lru = info . lru ; inState . importanceReasonCode = info . importanceReasonCode ; inState . importanceReasonPid = info . importanceReasonPid ; inState . lastTrimLevel = info . lastTrimLevel ; inState . pkgList = info . pkgList ; inState . processName = info . processName ; } }


signature:
public class ShadowActivityManager { /** * Sets the values to be returned by { @ link # getAppTasks ( ) } .
 * @ see # getAppTasks ( )
 * @ param tasks List of app tasks . */
public void setAppTasks ( List < ActivityManager . AppTask > appTasks ) { } }

implementation: this . appTasks . clear ( ) ; this . appTasks . addAll ( appTasks ) ;


signature:
public class AndroidManifest { /** * Allows ShadowPackageManager to provide
 * a resource index for initialising the resource attributes in all the metadata elements
 * @ param resourceTable used for getting resource IDs from string identifiers */
public void initMetaData ( ResourceTable resourceTable ) throws RoboNotFoundException { } }

implementation:
if ( ! packageNameIsOverridden ( ) ) { // packageName needs to be resolved
parseAndroidManifest ( ) ; } if ( applicationMetaData != null ) { applicationMetaData . init ( resourceTable , packageName ) ; } for ( PackageItemData receiver : receivers ) { receiver . getMetaData ( ) . init ( resourceTable , packageName ) ; } for ( ServiceData service : serviceDatas . values ( ) ) { service . getMetaData ( ) . init ( resourceTable , packageName ) ; } for ( ContentProviderData providerData : providers ) { providerData . getMetaData ( ) . init ( resourceTable , packageName ) ; }


signature:
public class AndroidManifest { /** * Returns all transitively reachable manifests , including this one , in order and without
 * duplicates . */
public List < AndroidManifest > getAllManifests ( ) { } }

implementation: Set < AndroidManifest > seenManifests = new HashSet < > ( ) ; List < AndroidManifest > uniqueManifests = new ArrayList < > ( ) ; addTransitiveManifests ( seenManifests , uniqueManifests ) ; return uniqueManifests ;


signature:
public class AndroidManifest { /** * Returns data for the broadcast receiver with the provided name from this manifest . If no
 * receiver with the class name can be found , returns null .
 * @ param className the fully resolved class name of the receiver
 * @ return data for the receiver or null if it cannot be found */
public @ Nullable BroadcastReceiverData getBroadcastReceiver ( String className ) { } }

implementation: parseAndroidManifest ( ) ; for ( BroadcastReceiverData receiver : receivers ) { if ( receiver . getName ( ) . equals ( className ) ) { return receiver ; } } return null ;


signature:
public class ShadowNotificationManager { /** * Delete a notification channel group and all notification channels associated with the group .
 * This method will not notify any NotificationListenerService of resulting changes to
 * notification channel groups nor to notification channels . */
@ Implementation ( minSdk = Build . VERSION_CODES . O ) protected void deleteNotificationChannelGroup ( String channelGroupId ) { } }

implementation:
if ( getNotificationChannelGroup ( channelGroupId ) != null ) { // Deleting a channel group also deleted all associated channels . See
// https : / / developer . android . com / reference / android / app / NotificationManager . html # deleteNotificationChannelGroup % 28java . lang . String % 29
// for more info .
for ( /* NotificationChannel */
Object channel : getNotificationChannels ( ) ) { String groupId = ReflectionHelpers . callInstanceMethod ( channel , "getGroup" ) ; if ( channelGroupId . equals ( groupId ) ) { String channelId = ReflectionHelpers . callInstanceMethod ( channel , "getId" ) ; deleteNotificationChannel ( channelId ) ; } } notificationChannelGroups . remove ( channelGroupId ) ; }


signature:
public class ShadowNotificationManager { /** * Returns a copy of { @ code automaticZenRule } . */
private AutomaticZenRule copyAutomaticZenRule ( AutomaticZenRule automaticZenRule ) { } }

implementation:
Parcel parcel = Parcel . obtain ( ) ; try { automaticZenRule . writeToParcel ( parcel , /* flags = */
0 ) ; parcel . setDataPosition ( 0 ) ; return new AutomaticZenRule ( parcel ) ; } finally { parcel . recycle ( ) ; }


signature: public class String8 { String8 getPathLeaf ( ) { } }

implementation: final int cp ; final String buf = mString . toString ( ) ; cp = buf . lastIndexOf ( '/' ) ; if ( cp == - 1 ) { return new String8 ( this ) ; } else { return new String8 ( buf . substring ( cp + 1 ) ) ; }


signature:
public class String8 { /** * Helper function for finding the start of an extension in a pathname .
 * Returns a index inside mString , or - 1 if no extension was found . */
private int find_extension ( ) { } }

implementation:
int lastSlashIndex ; final StringBuilder str = mString ; // only look at the filename
lastSlashIndex = str . lastIndexOf ( File . pathSeparator ) ; if ( lastSlashIndex == - 1 ) { lastSlashIndex = 0 ; } else { lastSlashIndex ++ ; } // find the last dot
return str . lastIndexOf ( "." , lastSlashIndex ) ;


signature:
public class ShadowMap { /** * todo : some caching would probably be nice here . . . */
private ShadowInfo checkShadowPickers ( String instrumentedClassName , Class < ? > clazz ) { } }

implementation: String shadowPickerClassName = shadowPickers . get ( instrumentedClassName ) ; if ( shadowPickerClassName == null ) { return null ; } return pickShadow ( instrumentedClassName , clazz , shadowPickerClassName ) ;


signature:
public class ShadowCaptioningManager { /** * Sets the value to be returned by { @ link CaptioningManager # getFontScale ( ) } */
public void setFontScale ( float fontScale ) { } }

implementation: this . fontScale = fontScale ; for ( CaptioningChangeListener captioningChangeListener : listeners ) { captioningChangeListener . onFontScaleChanged ( fontScale ) ; }


signature:
public class ShadowLegacyAsyncTask { /** * Enqueue a call to { @ link AsyncTask # onProgressUpdate ( Object [ ] ) } on UI looper ( or run it
 * immediately if the looper it is not paused ) .
 * @ param values The progress values to update the UI with .
 * @ see AsyncTask # publishProgress ( Object [ ] ) */
@ Implementation protected void publishProgress ( final Progress ... values ) { } }

implementation: ShadowApplication . getInstance ( ) . getForegroundThreadScheduler ( ) . post ( new Runnable ( ) { @ Override public void run ( ) { getBridge ( ) . onProgressUpdate ( values ) ; } } ) ;


signature:
public class ConfigurationV25 { /** * Returns a string representation of the configuration that can be parsed
 * by build tools ( like AAPT ) .
 * @ hide */
public static String resourceQualifierString ( Configuration config , DisplayMetrics displayMetrics ) { } }

implementation: return resourceQualifierString ( config , displayMetrics , true ) ;


signature:
public class ShadowBluetoothDevice { /** * Causes { @ link BluetoothGattCallback # onConnectionStateChange to be called for every GATT client .
 * @ param status Status of the GATT operation
 * @ param newState The new state of the GATT profile */
public void simulateGattConnectionChange ( int status , int newState ) { } }

implementation: for ( BluetoothGatt bluetoothGatt : bluetoothGatts ) { ShadowBluetoothGatt shadowBluetoothGatt = Shadow . extract ( bluetoothGatt ) ; BluetoothGattCallback gattCallback = shadowBluetoothGatt . getGattCallback ( ) ; gattCallback . onConnectionStateChange ( bluetoothGatt , status , newState ) ; }


signature:
public class SandboxClassLoader { /** * TODO ( b / 65488446 ) : Use a public API once one is available . */
private static URL [ ] parseJavaClassPath ( ) { } }

implementation:
ImmutableList . Builder < URL > urls = ImmutableList . builder ( ) ; for ( String entry : Splitter . on ( PATH_SEPARATOR . value ( ) ) . split ( JAVA_CLASS_PATH . value ( ) ) ) { try { try { urls . add ( new File ( entry ) . toURI ( ) . toURL ( ) ) ; } catch ( SecurityException e ) { // File . toURI checks to see if the file is a directory
urls . add ( new URL ( "file" , null , new File ( entry ) . getAbsolutePath ( ) ) ) ; } } catch ( MalformedURLException e ) { Logger . strict ( "malformed classpath entry: " + entry , e ) ; } } return urls . build ( ) . toArray ( new URL [ 0 ] ) ;


signature:
public class ShadowBitmapDrawable { /** * Draws the contained bitmap onto the canvas at 0,0 with a default { @ code Paint }
 * @ param canvas the canvas to draw on */
@ Implementation protected void draw ( Canvas canvas ) { } }

implementation: Paint paint = new Paint ( ) ; paint . setColorFilter ( colorFilter ) ; canvas . drawBitmap ( realBitmapDrawable . getBitmap ( ) , 0 , 0 , paint ) ;


signature:
public class ShadowBitmapDrawable { /** * Returns the resource id that this { @ code BitmapDrawable } was loaded from . This lets
 * your tests assert that the bitmap is correct without having to actually load the bitmap .
 * @ return resource id from which this { @ code BitmapDrawable } was loaded
 * @ deprecated use ShadowBitmap # getCreatedFromResId ( ) instead . */
@ Deprecated @ Override public int getCreatedFromResId ( ) { } }

implementation: ShadowBitmap shadowBitmap = Shadow . extract ( realBitmapDrawable . getBitmap ( ) ) ; return shadowBitmap . getCreatedFromResId ( ) ;


signature:
public class UnsafeAccess { /** * Returns the Java version as an int value .
 * @ return the Java version as an int value ( 8 , 9 , etc . ) */
private static int getJavaVersion ( ) { } }

implementation:
String version = System . getProperty ( "java.version" ) ; assert version != null ; if ( version . startsWith ( "1." ) ) { version = version . substring ( 2 ) ; } // Allow these formats :
// 1.8.0_72 - ea
// 9 - ea
// 9.0.1
int dotPos = version . indexOf ( '.' ) ; int dashPos = version . indexOf ( '-' ) ; return Integer . parseInt ( version . substring ( 0 , dotPos > - 1 ? dotPos : dashPos > - 1 ? dashPos : 1 ) ) ;


signature:
public class ShadowViewGroup { /** * Returns a string representation of this { @ code ViewGroup } by concatenating all of the
 * strings contained in all of the descendants of this { @ code ViewGroup } . */
@ Override public String innerText ( ) { } }

implementation: StringBuilder innerText = new StringBuilder ( ) ; String delimiter = "" ; for ( int i = 0 ; i < realViewGroup . getChildCount ( ) ; i ++ ) { View child = realViewGroup . getChildAt ( i ) ; ShadowView shadowView = Shadow . extract ( child ) ; String childText = shadowView . innerText ( ) ; if ( childText . length ( ) > 0 ) { innerText . append ( delimiter ) ; delimiter = " " ; } innerText . append ( childText ) ; } return innerText . toString ( ) ;


signature:
public class ShadowViewGroup { /** * Dumps the state of this { @ code ViewGroup } to { @ code System . out } .
 * @ deprecated - Please use { @ link androidx . test . espresso . util . HumanReadables # describe ( View ) } */
@ Override @ Deprecated public void dump ( PrintStream out , int indent ) { } }

implementation: dumpFirstPart ( out , indent ) ; if ( realViewGroup . getChildCount ( ) > 0 ) { out . println ( ">" ) ; for ( int i = 0 ; i < realViewGroup . getChildCount ( ) ; i ++ ) { View child = realViewGroup . getChildAt ( i ) ; ShadowView shadowChild = Shadow . extract ( child ) ; shadowChild . dump ( out , indent + 2 ) ; } dumpIndent ( out , indent ) ; out . println ( "</" + realView . getClass ( ) . getSimpleName ( ) + ">" ) ; } else { out . println ( "/>" ) ; }


signature:
public class ShadowMotionEvent { /** * TODO ( brettchabot ) : properly handle displayId */
@ Implementation ( minSdk = android . os . Build . VERSION_CODES . Q ) @ HiddenApi protected static long nativeInitialize ( long nativePtr , int deviceId , int source , int displayId , int action , int flags , int edgeFlags , int metaState , int buttonState , int classification , float xOffset , float yOffset , float xPrecision , float yPrecision , long downTimeNanos , long eventTimeNanos , int pointerCount , PointerProperties [ ] pointerIds , PointerCoords [ ] pointerCoords ) { } }

implementation: return nativeInitialize ( nativePtr , deviceId , source , action , flags , edgeFlags , metaState , buttonState , xOffset , yOffset , xPrecision , yPrecision , downTimeNanos , eventTimeNanos , pointerCount , pointerIds , pointerCoords ) ;


signature:
public class ShadowMotionEvent { /** * shadow this directly as opposed to nativeTransform because need access to ShadowMatrix */
@ Implementation protected final void transform ( Matrix matrix ) { } }

implementation: checkNotNull ( matrix ) ; NativeInput . MotionEvent event = getNativeMotionEvent ( ) ; ShadowMatrix shadowMatrix = Shadow . extract ( matrix ) ; float [ ] m = new float [ 9 ] ; shadowMatrix . getValues ( m ) ; event . transform ( m ) ;


signature:
public class ShadowBluetoothServerSocket { /** * May block the current thread and wait until { @ link BluetoothDevice } is offered via
 * { @ link # deviceConnected ( BluetoothDevice ) } method or timeout occurred .
 * @ return socket of the connected bluetooth device
 * @ throws IOException if socket has been closed , thread interrupted while waiting or timeout has
 * occurred . */
@ Implementation protected BluetoothSocket accept ( int timeout ) throws IOException { } }

implementation: if ( closed ) { throw new IOException ( "Socket closed" ) ; } BluetoothSocket socket ; try { socket = timeout == - 1 ? sockets . take ( ) : sockets . poll ( timeout , TimeUnit . MILLISECONDS ) ; } catch ( InterruptedException e ) { throw new IOException ( e ) ; } if ( socket == null ) { throw new IOException ( "Timeout occurred" ) ; } socket . connect ( ) ; return socket ;


signature:
public class ShadowBluetoothServerSocket { /** * Creates { @ link BluetoothSocket } for the given device and makes this socket available
 * immediately in the { @ link # accept ( int ) } method . */
public BluetoothSocket deviceConnected ( BluetoothDevice device ) { } }

implementation: BluetoothSocket socket = Shadow . newInstanceOf ( BluetoothSocket . class ) ; ReflectionHelpers . setField ( socket , "mDevice" , device ) ; sockets . offer ( socket ) ; return socket ;


signature:
public class ShadowSubscriptionManager { /** * Returns subscription that were set via { @ link # setActiveSubscriptionInfoList } if it can find
 * one with the specified id or null if none found . */
@ Implementation ( minSdk = LOLLIPOP_MR1 ) protected SubscriptionInfo getActiveSubscriptionInfo ( int subId ) { } }

implementation: if ( subscriptionList == null ) { return null ; } for ( SubscriptionInfo info : subscriptionList ) { if ( info . getSubscriptionId ( ) == subId ) { return info ; } } return null ;


signature:
public class ShadowSubscriptionManager { /** * Returns subscription that were set via { @ link # setActiveSubscriptionInfoList } if it can find
 * one with the specified slot index or null if none found . */
@ Implementation ( minSdk = N ) protected SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex ( int slotIndex ) { } }

implementation: if ( subscriptionList == null ) { return null ; } for ( SubscriptionInfo info : subscriptionList ) { if ( info . getSimSlotIndex ( ) == slotIndex ) { return info ; } } return null ;


signature:
public class ShadowSubscriptionManager { /** * Sets the active list of { @ link SubscriptionInfo } . This call internally triggers { @ link
 * OnSubscriptionsChangedListener # onSubscriptionsChanged ( ) } to all the listeners . */
public void setActiveSubscriptionInfos ( SubscriptionInfo ... infos ) { } }

implementation: if ( infos == null ) { setActiveSubscriptionInfoList ( ImmutableList . of ( ) ) ; } else { setActiveSubscriptionInfoList ( Arrays . asList ( infos ) ) ; }


signature:
public class ShadowSubscriptionManager { /** * Sets the active list of { @ link SubscriptionInfo } . This call internally triggers { @ link
 * OnSubscriptionsChangedListener # onSubscriptionsChanged ( ) } to all the listeners . */
public void setAvailableSubscriptionInfos ( SubscriptionInfo ... infos ) { } }

implementation: if ( infos == null ) { setAvailableSubscriptionInfoList ( ImmutableList . of ( ) ) ; } else { setAvailableSubscriptionInfoList ( Arrays . asList ( infos ) ) ; }


signature:
public class ShadowSubscriptionManager { /** * Returns subscription Ids that were set via { @ link # setActiveSubscriptionInfoList } . */
@ Implementation ( minSdk = LOLLIPOP_MR1 ) @ HiddenApi protected int [ ] getActiveSubscriptionIdList ( ) { } }

implementation: final List < SubscriptionInfo > infos = getActiveSubscriptionInfoList ( ) ; if ( infos == null ) { return new int [ 0 ] ; } int [ ] ids = new int [ infos . size ( ) ] ; for ( int i = 0 ; i < infos . size ( ) ; i ++ ) { ids [ i ] = infos . get ( i ) . getSubscriptionId ( ) ; } return ids ;


signature:
public class ShadowSubscriptionManager { /** * If isNetworkRoaming is set , it will mark the provided sim subscriptionId as roaming in a local
 * cache . If isNetworkRoaming is unset it will remove the subscriptionId from the local cache . The
 * local cache is used to provide roaming status returned by { @ link # isNetworkRoaming } . */
public void setNetworkRoamingStatus ( int simSubscriptionId , boolean isNetworkRoaming ) { } }

implementation: if ( isNetworkRoaming ) { roamingSimSubscriptionIds . add ( simSubscriptionId ) ; } else { roamingSimSubscriptionIds . remove ( simSubscriptionId ) ; }


signature:
public class ShadowSubscriptionManager { /** * Uses the map of subscription IDs to phone IDs managed by { @ link putPhoneId } and { @ link
 * removePhoneId } to return the phone ID for a given subscription ID . */
@ Implementation ( minSdk = LOLLIPOP_MR1 , maxSdk = P ) @ HiddenApi protected static int getPhoneId ( int subId ) { } }

implementation: if ( phoneIds . containsKey ( subId ) ) { return phoneIds . get ( subId ) ; } return INVALID_PHONE_INDEX ;