signature:
public class ApkLoader { /** * Returns the ResourceTable for the compile time SDK . */
@ Nonnull synchronized public PackageResourceTable getCompileTimeSdkResourceTable ( ) { } }

implementation: if ( compiletimeSdkResourceTable == null ) { ResourceTableFactory resourceTableFactory = new ResourceTableFactory ( ) ; compiletimeSdkResourceTable = resourceTableFactory . newFrameworkResourceTable ( new ResourcePath ( android . R . class , null , null ) ) ; } return compiletimeSdkResourceTable ;


signature:
public class ShadowView { /** * Calls { @ code performClick ( ) } on a { @ code View } after ensuring that it and its ancestors are visible and that it
 * is enabled .
 * @ param view the view to click on
 * @ return true if { @ code View . OnClickListener } s were found and fired , false otherwise .
 * @ throws RuntimeException if the preconditions are not met .
 * @ deprecated Please use Espresso for view interactions */
@ Deprecated public static boolean clickOn ( View view ) { } }

implementation: ShadowView shadowView = Shadow . extract ( view ) ; return shadowView . checkedPerformClick ( ) ;


signature:
public class ShadowView { /** * Returns a textual representation of the appearance of the object .
 * @ param view the view to visualize
 * @ return Textual representation of the appearance of the object . */
public static String visualize ( View view ) { } }

implementation: Canvas canvas = new Canvas ( ) ; view . draw ( canvas ) ; ShadowCanvas shadowCanvas = Shadow . extract ( canvas ) ; return shadowCanvas . getDescription ( ) ;


signature:
public class ShadowView { /** * Emits an xml - like representation of the view to System . out .
 * @ param view the view to dump .
 * @ deprecated - Please use { @ link androidx . test . espresso . util . HumanReadables # describe ( View ) } */
@ SuppressWarnings ( "UnusedDeclaration" ) @ Deprecated public static void dump ( View view ) { } }

implementation: ShadowView shadowView = Shadow . extract ( view ) ; shadowView . dump ( ) ;


signature:
public class ShadowView { /** * Returns the text contained within this view .
 * @ param view the view to scan for text
 * @ return Text contained within this view . */
@ SuppressWarnings ( "UnusedDeclaration" ) public static String innerText ( View view ) { } }

implementation: ShadowView shadowView = Shadow . extract ( view ) ; return shadowView . innerText ( ) ;


signature:
public class ShadowView { /** * Dumps the status of this { @ code View } to { @ code System . out } at the given indentation level
 * @ param out Output stream .
 * @ param indent Indentation level .
 * @ deprecated - Please use { @ link androidx . test . espresso . util . HumanReadables # describe ( View ) } */
@ Deprecated public void dump ( PrintStream out , int indent ) { } }

implementation: dumpFirstPart ( out , indent ) ; out . println ( "/>" ) ;


signature:
public class InstrumentationConfiguration { /** * Determine if { @ link SandboxClassLoader } should instrument a given class .
 * @ param mutableClass The class to check .
 * @ return True if the class should be instrumented . */
public boolean shouldInstrument ( MutableClass mutableClass ) { } }

implementation: return ! ( mutableClass . isInterface ( ) || mutableClass . isAnnotation ( ) || mutableClass . hasAnnotation ( DoNotInstrument . class ) ) && ( isInInstrumentedPackage ( mutableClass . getName ( ) ) || instrumentedClasses . contains ( mutableClass . getName ( ) ) || mutableClass . hasAnnotation ( Instrument . class ) ) && ! ( classesToNotInstrument . contains ( mutableClass . getName ( ) ) ) && ! ( isInPackagesToNotInstrument ( mutableClass . getName ( ) ) ) ;


signature:
public class InstrumentationConfiguration { /** * Determine if { @ link SandboxClassLoader } should load a given class .
 * @ param name The fully - qualified class name .
 * @ return True if the class should be loaded . */
public boolean shouldAcquire ( String name ) { } }

implementation:
if ( CLASSES_TO_ALWAYS_ACQUIRE . contains ( name ) ) { return true ; } if ( name . equals ( "java.util.jar.StrictJarFile" ) ) { return true ; } // android . R and com . android . internal . R classes must be loaded from the framework jar
if ( name . matches ( "(android|com\\.android\\.internal)\\.R(\\$.+)?" ) ) { return true ; } // Hack . Fixes https : / / github . com / robolectric / robolectric / issues / 1864
if ( name . equals ( "javax.net.ssl.DistinguishedNameParser" ) || name . equals ( "javax.microedition.khronos.opengles.GL" ) ) { return true ; } for ( String packageName : packagesToNotAcquire ) { if ( name . startsWith ( packageName ) ) return false ; } // R classes must be loaded from system CP
boolean isRClass = name . matches ( ".*\\.R(|\\$[a-z]+)$" ) ; return ! isRClass && ! classesToNotAcquire . contains ( name ) ;


signature:
public class ShadowInstrumentation { /** * Returns the BroadcaseReceivers wrappers , matching intent ' s action and permissions . */
private List < Wrapper > getAppropriateWrappers ( Intent intent , String receiverPermission ) { } }

implementation: broadcastIntents . add ( intent ) ; List < Wrapper > result = new ArrayList < > ( ) ; List < Wrapper > copy = new ArrayList < > ( ) ; copy . addAll ( registeredReceivers ) ; String intentClass = intent . getComponent ( ) != null ? intent . getComponent ( ) . getClassName ( ) : null ; for ( Wrapper wrapper : copy ) { if ( ( hasMatchingPermission ( wrapper . broadcastPermission , receiverPermission ) && wrapper . intentFilter . matchAction ( intent . getAction ( ) ) ) || ( intentClass != null && intentClass . equals ( wrapper . broadcastReceiver . getClass ( ) . getName ( ) ) ) ) { final int match = wrapper . intentFilter . matchData ( intent . getType ( ) , intent . getScheme ( ) , intent . getData ( ) ) ; if ( match != IntentFilter . NO_MATCH_DATA && match != IntentFilter . NO_MATCH_TYPE ) { result . add ( wrapper ) ; } } } return result ;


signature:
public class ShadowInstrumentation { /** * Enforces that BroadcastReceivers invoked during an ordered broadcast run serially , passing
 * along their results . */
private ListenableFuture < BroadcastResultHolder > postIntent ( final Wrapper wrapper , final Intent intent , ListenableFuture < BroadcastResultHolder > oldResult , final AtomicBoolean abort , final Context context ) { } }

implementation:
final Handler scheduler = ( wrapper . scheduler != null ) ? wrapper . scheduler : getMainHandler ( context ) ; return Futures . transformAsync ( oldResult , new AsyncFunction < BroadcastResultHolder , BroadcastResultHolder > ( ) { @ Override public ListenableFuture < BroadcastResultHolder > apply ( BroadcastResultHolder broadcastResultHolder ) throws Exception { final BroadcastReceiver . PendingResult result = ShadowBroadcastPendingResult . create ( broadcastResultHolder . resultCode , broadcastResultHolder . resultData , broadcastResultHolder . resultExtras , true /* ordered */
) ; wrapper . broadcastReceiver . setPendingResult ( result ) ; scheduler . post ( ( ) -> { ShadowBroadcastReceiver shadowBroadcastReceiver = Shadow . extract ( wrapper . broadcastReceiver ) ; shadowBroadcastReceiver . onReceive ( context , intent , abort ) ; } ) ; return BroadcastResultHolder . transform ( result ) ; } } , directExecutor ( ) ) ;


signature:
public class ShadowInstrumentation { /** * Broadcasts the { @ code Intent } by iterating through the registered receivers , invoking their
 * filters including permissions , and calling { @ code onReceive ( Application , Intent ) } as
 * appropriate . Does not enqueue the { @ code Intent } for later inspection .
 * @ param context
 * @ param intent the { @ code Intent } to broadcast todo : enqueue the Intent for later inspection */
void sendBroadcastWithPermission ( Intent intent , String receiverPermission , Context context ) { } }

implementation: sendBroadcastWithPermission ( intent , receiverPermission , context , 0 ) ;


signature:
public class ShadowColor { /** * This is implemented in native code in the Android SDK .
 * < p > Since HSV = = HSB then the implementation from { @ link java . awt . Color } can be used , with a
 * small adjustment to the representation of the hue .
 * < p > { @ link java . awt . Color } represents hue as 0 . . 1 ( where 1 = = 100 % = = 360 degrees ) , while { @ link
 * android . graphics . Color } represents hue as 0 . . 360 degrees . The correct hue can be calculated by
 * multiplying with 360.
 * @ param red Red component
 * @ param green Green component
 * @ param blue Blue component
 * @ param hsv Array to store HSV components */
@ Implementation protected static void RGBToHSV ( int red , int green , int blue , float hsv [ ] ) { } }

implementation: java . awt . Color . RGBtoHSB ( red , green , blue , hsv ) ; hsv [ 0 ] = hsv [ 0 ] * 360 ;


signature:
public class ShadowOpenGLMatrix { /** * Multiplies two 4x4 matrices together and stores the result in a third 4x4 matrix . In matrix
 * notation : result = lhs x rhs . Due to the way matrix multiplication works , the result matrix
 * will have the same effect as first multiplying by the rhs matrix , then multiplying by the lhs
 * matrix . This is the opposite of what you might expect .
 * < p > The same float array may be passed for result , lhs , and / or rhs . However , the result element
 * values are undefined if the result elements overlap either the lhs or rhs elements .
 * @ param result The float array that holds the result .
 * @ param resultOffset The offset into the result array where the result is stored .
 * @ param lhs The float array that holds the left - hand - side matrix .
 * @ param lhsOffset The offset into the lhs array where the lhs is stored
 * @ param rhs The float array that holds the right - hand - side matrix .
 * @ param rhsOffset The offset into the rhs array where the rhs is stored .
 * @ throws IllegalArgumentException if result , lhs , or rhs are null , or if resultOffset + 16 >
 * result . length or lhsOffset + 16 > lhs . length or rhsOffset + 16 > rhs . length . */
@ Implementation protected static void multiplyMM ( float [ ] result , int resultOffset , float [ ] lhs , int lhsOffset , float [ ] rhs , int rhsOffset ) { } }

implementation: if ( result == null ) { throw new IllegalArgumentException ( "result == null" ) ; } if ( lhs == null ) { throw new IllegalArgumentException ( "lhs == null" ) ; } if ( rhs == null ) { throw new IllegalArgumentException ( "rhs == null" ) ; } if ( resultOffset + 16 > result . length ) { throw new IllegalArgumentException ( "resultOffset + 16 > result.length" ) ; } if ( lhsOffset + 16 > lhs . length ) { throw new IllegalArgumentException ( "lhsOffset + 16 > lhs.length" ) ; } if ( rhsOffset + 16 > rhs . length ) { throw new IllegalArgumentException ( "rhsOffset + 16 > rhs.length" ) ; } for ( int i = 0 ; i < 4 ; i ++ ) { final float rhs_i0 = rhs [ I ( i , 0 , rhsOffset ) ] ; float ri0 = lhs [ I ( 0 , 0 , lhsOffset ) ] * rhs_i0 ; float ri1 = lhs [ I ( 0 , 1 , lhsOffset ) ] * rhs_i0 ; float ri2 = lhs [ I ( 0 , 2 , lhsOffset ) ] * rhs_i0 ; float ri3 = lhs [ I ( 0 , 3 , lhsOffset ) ] * rhs_i0 ; for ( int j = 1 ; j < 4 ; j ++ ) { final float rhs_ij = rhs [ I ( i , j , rhsOffset ) ] ; ri0 += lhs [ I ( j , 0 , lhsOffset ) ] * rhs_ij ; ri1 += lhs [ I ( j , 1 , lhsOffset ) ] * rhs_ij ; ri2 += lhs [ I ( j , 2 , lhsOffset ) ] * rhs_ij ; ri3 += lhs [ I ( j , 3 , lhsOffset ) ] * rhs_ij ; } result [ I ( i , 0 , resultOffset ) ] = ri0 ; result [ I ( i , 1 , resultOffset ) ] = ri1 ; result [ I ( i , 2 , resultOffset ) ] = ri2 ; result [ I ( i , 3 , resultOffset ) ] = ri3 ; }


signature:
public class ShadowOpenGLMatrix { /** * Multiplies a 4 element vector by a 4x4 matrix and stores the result in a 4 - element column
 * vector . In matrix notation : result = lhs x rhs
 * < p > The same float array may be passed for resultVec , lhsMat , and / or rhsVec . However , the
 * resultVec element values are undefined if the resultVec elements overlap either the lhsMat or
 * rhsVec elements .
 * @ param resultVec The float array that holds the result vector .
 * @ param resultVecOffset The offset into the result array where the result vector is stored .
 * @ param lhsMat The float array that holds the left - hand - side matrix .
 * @ param lhsMatOffset The offset into the lhs array where the lhs is stored
 * @ param rhsVec The float array that holds the right - hand - side vector .
 * @ param rhsVecOffset The offset into the rhs vector where the rhs vector is stored .
 * @ throws IllegalArgumentException if resultVec , lhsMat , or rhsVec are null , or if
 * resultVecOffset + 4 > resultVec . length or lhsMatOffset + 16 > lhsMat . length or rhsVecOffset
 * + 4 > rhsVec . length . */
@ Implementation protected static void multiplyMV ( float [ ] resultVec , int resultVecOffset , float [ ] lhsMat , int lhsMatOffset , float [ ] rhsVec , int rhsVecOffset ) { } }

implementation: if ( resultVec == null ) { throw new IllegalArgumentException ( "resultVec == null" ) ; } if ( lhsMat == null ) { throw new IllegalArgumentException ( "lhsMat == null" ) ; } if ( rhsVec == null ) { throw new IllegalArgumentException ( "rhsVec == null" ) ; } if ( resultVecOffset + 4 > resultVec . length ) { throw new IllegalArgumentException ( "resultVecOffset + 4 > resultVec.length" ) ; } if ( lhsMatOffset + 16 > lhsMat . length ) { throw new IllegalArgumentException ( "lhsMatOffset + 16 > lhsMat.length" ) ; } if ( rhsVecOffset + 4 > rhsVec . length ) { throw new IllegalArgumentException ( "rhsVecOffset + 4 > rhsVec.length" ) ; } final float x = rhsVec [ rhsVecOffset + 0 ] ; final float y = rhsVec [ rhsVecOffset + 1 ] ; final float z = rhsVec [ rhsVecOffset + 2 ] ; final float w = rhsVec [ rhsVecOffset + 3 ] ; resultVec [ resultVecOffset + 0 ] = lhsMat [ I ( 0 , 0 , lhsMatOffset ) ] * x + lhsMat [ I ( 1 , 0 , lhsMatOffset ) ] * y + lhsMat [ I ( 2 , 0 , lhsMatOffset ) ] * z + lhsMat [ I ( 3 , 0 , lhsMatOffset ) ] * w ; resultVec [ resultVecOffset + 1 ] = lhsMat [ I ( 0 , 1 , lhsMatOffset ) ] * x + lhsMat [ I ( 1 , 1 , lhsMatOffset ) ] * y + lhsMat [ I ( 2 , 1 , lhsMatOffset ) ] * z + lhsMat [ I ( 3 , 1 , lhsMatOffset ) ] * w ; resultVec [ resultVecOffset + 2 ] = lhsMat [ I ( 0 , 2 , lhsMatOffset ) ] * x + lhsMat [ I ( 1 , 2 , lhsMatOffset ) ] * y + lhsMat [ I ( 2 , 2 , lhsMatOffset ) ] * z + lhsMat [ I ( 3 , 2 , lhsMatOffset ) ] * w ; resultVec [ resultVecOffset + 3 ] = lhsMat [ I ( 0 , 3 , lhsMatOffset ) ] * x + lhsMat [ I ( 1 , 3 , lhsMatOffset ) ] * y + lhsMat [ I ( 2 , 3 , lhsMatOffset ) ] * z + lhsMat [ I ( 3 , 3 , lhsMatOffset ) ] * w ;


signature:
public class ShadowTrace { /** * Starts a new trace section with given name . */
@ Implementation ( minSdk = JELLY_BEAN_MR2 ) protected static void beginSection ( String sectionName ) { } }

implementation: if ( Trace . isTagEnabled ( TRACE_TAG_APP ) ) { if ( crashOnIncorrectUsage ) { if ( sectionName . length ( ) > MAX_SECTION_NAME_LEN ) { throw new IllegalArgumentException ( "sectionName is too long" ) ; } } else if ( sectionName == null ) { Log . w ( TAG , "Section name cannot be null" ) ; return ; } else if ( sectionName . length ( ) > MAX_SECTION_NAME_LEN ) { Log . w ( TAG , "Section name is too long" ) ; return ; } synchronized ( lock ) { currentSections . addFirst ( sectionName ) ; } }


signature:
public class ShadowTrace { /** * Ends the most recent active trace section .
 * @ throws { @ link AssertionError } if called without any active trace section . */
@ Implementation ( minSdk = JELLY_BEAN_MR2 ) protected static void endSection ( ) { } }

implementation: if ( Trace . isTagEnabled ( TRACE_TAG_APP ) ) { synchronized ( lock ) { if ( currentSections . isEmpty ( ) ) { Log . e ( TAG , "Trying to end a trace section that was never started" ) ; return ; } previousSections . offer ( currentSections . removeFirst ( ) ) ; } }


signature:
public class Injector { /** * Finds an instance for the given class . Calls are guaranteed idempotent . */
@ Nonnull public < T > T getInstance ( @ Nonnull Class < T > type ) { } }

implementation: return getInstance ( new Key < > ( type ) ) ;


signature:
public class Injector { /** * Finds an instance for the given key . Calls are guaranteed idempotent . */
@ Nonnull private < T > T getInstance ( @ Nonnull Key < T > key ) { } }

implementation: try { return getInstanceInternal ( key ) ; } catch ( UnsatisfiedDependencyException e ) { throw e . asInjectionException ( key ) ; }


signature:
public class Injector { /** * Finds a provider for the given key .
 * Calls are guaranteed idempotent and non - blocking . */
@ SuppressWarnings ( "unchecked" ) @ Nonnull private synchronized < T > Provider < T > getProvider ( final Key < T > key ) { } }

implementation:
// Previously - gotten providers ( including those from subinjectors ) will already be present .
return ( Provider < T > ) providers . computeIfAbsent ( key , k -> { // @ AutoFactory requests are always handled by the top - level injector .
if ( key . isAutoFactory ( ) ) { return memoized ( new ScopeBuilderProvider < > ( key . getDependencyClass ( ) ) ) ; } // Find a provider locally .
return findLocalProvider ( key ) ; } ) ;


signature: public class CppAssetManager { public boolean addAssetPath ( String8 path , Ref < Integer > cookie , boolean appAsLib ) { } }

implementation: return addAssetPath ( path , cookie , appAsLib , false ) ;


signature:
public class CppAssetManager { /** * Open an asset .
 * The data could be in any asset path . Each asset path could be :
 * - A directory on disk .
 * - A Zip archive , uncompressed or compressed .
 * If the file is in a directory , it could have a . gz suffix , meaning it is compressed .
 * We should probably reject requests for " illegal " filenames , e . g . those
 * with illegal characters or " . . / " backward relative paths . */
public Asset open ( final String fileName , AccessMode mode ) { } }

implementation:
synchronized ( mLock ) { LOG_FATAL_IF ( mAssetPaths . isEmpty ( ) , "No assets added to AssetManager" ) ; String8 assetName = new String8 ( kAssetsRoot ) ; assetName . appendPath ( fileName ) ; /* * For each top - level asset path , search for the asset . */
int i = mAssetPaths . size ( ) ; while ( i > 0 ) { i -- ; ALOGV ( "Looking for asset '%s' in '%s'\n" , assetName . string ( ) , mAssetPaths . get ( i ) . path . string ( ) ) ; Asset pAsset = openNonAssetInPathLocked ( assetName . string ( ) , mode , mAssetPaths . get ( i ) ) ; if ( pAsset != null ) { return Objects . equals ( pAsset , kExcludedAsset ) ? null : pAsset ; } } return null ; }


signature:
public class CppAssetManager { /** * Open a non - asset file as if it were an asset .
 * The " fileName " is the partial path starting from the application name . */
public Asset openNonAsset ( final String fileName , AccessMode mode , Ref < Integer > outCookie ) { } }

implementation:
synchronized ( mLock ) { // AutoMutex _ l ( mLock ) ;
LOG_FATAL_IF ( mAssetPaths . isEmpty ( ) , "No assets added to AssetManager" ) ; /* * For each top - level asset path , search for the asset . */
int i = mAssetPaths . size ( ) ; while ( i > 0 ) { i -- ; ALOGV ( "Looking for non-asset '%s' in '%s'\n" , fileName , mAssetPaths . get ( i ) . path . string ( ) ) ; Asset pAsset = openNonAssetInPathLocked ( fileName , mode , mAssetPaths . get ( i ) ) ; if ( pAsset != null ) { if ( outCookie != null ) { outCookie . set ( i + 1 ) ; } return pAsset != kExcludedAsset ? pAsset : null ; } } return null ; }


signature:
public class CppAssetManager { /** * Get the type of a file */
FileType getFileType ( final String fileName ) { } }

implementation:
// deviate from Android CPP implementation here . Assume fileName is a complete path
// rather than limited to just asset namespace
File assetFile = new File ( fileName ) ; if ( ! assetFile . exists ( ) ) { return FileType . kFileTypeNonexistent ; } else if ( assetFile . isFile ( ) ) { return FileType . kFileTypeRegular ; } else if ( assetFile . isDirectory ( ) ) { return kFileTypeDirectory ; } return FileType . kFileTypeNonexistent ; // Asset pAsset = null ;
// * Open the asset . This is less efficient than simply finding the
// * file , but it ' s not too bad ( we don ' t uncompress or mmap data until
// * the first read ( ) call ) .
// pAsset = open ( fileName , Asset . AccessMode . ACCESS _ STREAMING ) ;
// / / delete pAsset ;
// if ( pAsset = = null ) {
// return FileType . kFileTypeNonexistent ;
// } else {
// return FileType . kFileTypeRegular ;


signature:
public class CppAssetManager { /** * Open a non - asset file as if it were an asset , searching for it in the
 * specified app .
 * Pass in a null values for " appName " if the common app directory should
 * be used . */
static Asset openNonAssetInPathLocked ( final String fileName , AccessMode mode , final asset_path ap ) { } }

implementation:
Asset pAsset = null ; /* look at the filesystem on disk */
if ( ap . type == kFileTypeDirectory ) { String8 path = new String8 ( ap . path ) ; path . appendPath ( fileName ) ; pAsset = openAssetFromFileLocked ( path , mode ) ; if ( pAsset == null ) { /* try again , this time with " . gz " */
path . append ( ".gz" ) ; pAsset = openAssetFromFileLocked ( path , mode ) ; } if ( pAsset != null ) { // printf ( " FOUND NA ' % s ' on disk \ n " , fileName ) ;
pAsset . setAssetSource ( path ) ; } /* look inside the zip file */
} else { String8 path = new String8 ( fileName ) ; /* check the appropriate Zip file */
ZipFileRO pZip = getZipFileLocked ( ap ) ; if ( pZip != null ) { // printf ( " GOT zip , checking NA ' % s ' \ n " , ( final char * ) path ) ;
ZipEntryRO entry = pZip . findEntryByName ( path . string ( ) ) ; if ( entry != null ) { // printf ( " FOUND NA in Zip file for % s \ n " , appName ? appName : kAppCommon ) ;
pAsset = openAssetFromZipLocked ( pZip , entry , mode , path ) ; pZip . releaseEntry ( entry ) ; } } if ( pAsset != null ) { /* create a " source " name , for debug / display */
pAsset . setAssetSource ( createZipSourceNameLocked ( ap . path , new String8 ( ) , new String8 ( fileName ) ) ) ; } } return pAsset ;


signature:
public class CppAssetManager { /** * Create a " source name " for a file from a Zip archive . */
static String8 createZipSourceNameLocked ( final String8 zipFileName , final String8 dirName , final String8 fileName ) { } }

implementation: String8 sourceName = new String8 ( "zip:" ) ; sourceName . append ( zipFileName . string ( ) ) ; sourceName . append ( ":" ) ; if ( dirName . length ( ) > 0 ) { sourceName . appendPath ( dirName . string ( ) ) ; } sourceName . appendPath ( fileName . string ( ) ) ; return sourceName ;


signature:
public class CppAssetManager { /** * Create a path to a loose asset ( asset - base / app / rootDir ) . */
static String8 createPathNameLocked ( final asset_path ap , final String rootDir ) { } }

implementation: String8 path = new String8 ( ap . path ) ; if ( rootDir != null ) { path . appendPath ( rootDir ) ; } return path ;


signature:
public class CppAssetManager { /** * Return a pointer to one of our open Zip archives . Returns null if no
 * matching Zip file exists . */
static ZipFileRO getZipFileLocked ( final asset_path ap ) { } }

implementation: ALOGV ( "getZipFileLocked() in %s\n" , CppAssetManager . class ) ; return mZipSet . getZip ( ap . path . string ( ) ) ;


signature:
public class CppAssetManager { /** * Try to open an asset from a file on disk .
 * If the file is compressed with gzip , we seek to the start of the
 * deflated data and pass that in ( just like we would for a Zip archive ) .
 * For uncompressed data , we may already have an mmap ( ) ed version sitting
 * around . If so , we want to hand that to the Asset instead .
 * This returns null if the file doesn ' t exist , couldn ' t be opened , or
 * claims to be a " . gz " but isn ' t . */
static Asset openAssetFromFileLocked ( final String8 pathName , AccessMode mode ) { } }

implementation:
Asset pAsset = null ; if ( pathName . getPathExtension ( ) . toLowerCase ( ) . equals ( ".gz" ) ) { // printf ( " TRYING ' % s ' \ n " , ( final char * ) pathName ) ;
pAsset = Asset . createFromCompressedFile ( pathName . string ( ) , mode ) ; } else { // printf ( " TRYING ' % s ' \ n " , ( final char * ) pathName ) ;
pAsset = Asset . createFromFile ( pathName . string ( ) , mode ) ; } return pAsset ;


signature:
public class CppAssetManager { /** * Given an entry in a Zip archive , create a new Asset object .
 * If the entry is uncompressed , we may want to create or share a
 * slice of shared memory . */
static Asset openAssetFromZipLocked ( final ZipFileRO pZipFile , final ZipEntryRO entry , AccessMode mode , final String8 entryName ) { } }

implementation:
Asset pAsset = null ; // TODO : look for previously - created shared memory slice ?
final Ref < Short > method = new Ref < > ( ( short ) 0 ) ; final Ref < Long > uncompressedLen = new Ref < > ( 0L ) ; // printf ( " USING Zip ' % s ' \ n " , pEntry . getFileName ( ) ) ;
if ( ! pZipFile . getEntryInfo ( entry , method , uncompressedLen , null , null , null , null ) ) { ALOGW ( "getEntryInfo failed\n" ) ; return null ; } // return Asset . createFromZipEntry ( pZipFile , entry , entryName ) ;
FileMap dataMap = pZipFile . createEntryFileMap ( entry ) ; // if ( dataMap = = null ) {
// ALOGW ( " create map from entry failed \ n " ) ;
// return null ;
if ( method . get ( ) == ZipFileRO . kCompressStored ) { pAsset = Asset . createFromUncompressedMap ( dataMap , mode ) ; ALOGV ( "Opened uncompressed entry %s in zip %s mode %s: %s" , entryName . string ( ) , pZipFile . mFileName , mode , pAsset ) ; } else { pAsset = Asset . createFromCompressedMap ( dataMap , toIntExact ( uncompressedLen . get ( ) ) , mode ) ; ALOGV ( "Opened compressed entry %s in zip %s mode %s: %s" , entryName . string ( ) , pZipFile . mFileName , mode , pAsset ) ; } if ( pAsset == null ) { /* unexpected */
ALOGW ( "create from segment failed\n" ) ; } return pAsset ;


signature:
public class CppAssetManager { /** * Open a directory in the asset namespace .
 * An " asset directory " is simply the combination of all asset paths ' " assets / " directories .
 * Pass in " " for the root dir . */
public AssetDir openDir ( final String dirName ) { } }

implementation:
synchronized ( mLock ) { AssetDir pDir = null ; final Ref < SortedVector < AssetDir . FileInfo > > pMergedInfo ; LOG_FATAL_IF ( mAssetPaths . isEmpty ( ) , "No assets added to AssetManager" ) ; Preconditions . checkNotNull ( dirName ) ; // printf ( " + + + openDir ( % s ) in ' % s ' \ n " , dirName , ( final char * ) mAssetBase ) ;
pDir = new AssetDir ( ) ; /* * Scan the various directories , merging what we find into a single
 * vector . We want to scan them in reverse priority order so that
 * the " . EXCLUDE " processing works correctly . Also , if we decide we
 * want to remember where the file is coming from , we ' ll get the right
 * version .
 * We start with Zip archives , then do loose files . */
pMergedInfo = new Ref < > ( new SortedVector < AssetDir . FileInfo > ( ) ) ; int i = mAssetPaths . size ( ) ; while ( i > 0 ) { i -- ; final asset_path ap = mAssetPaths . get ( i ) ; if ( ap . type == FileType . kFileTypeRegular ) { ALOGV ( "Adding directory %s from zip %s" , dirName , ap . path . string ( ) ) ; scanAndMergeZipLocked ( pMergedInfo , ap , kAssetsRoot , dirName ) ; } else { ALOGV ( "Adding directory %s from dir %s" , dirName , ap . path . string ( ) ) ; scanAndMergeDirLocked ( pMergedInfo , ap , kAssetsRoot , dirName ) ; } } // # if 0
// printf ( " FILE LIST : \ n " ) ;
// for ( i = 0 ; i < ( int ) pMergedInfo . size ( ) ; i + + ) {
// printf ( " % d : ( % d ) ' % s ' \ n " , i ,
// pMergedInfo . itemAt ( i ) . getFileType ( ) ,
// ( final char * ) pMergedInfo . itemAt ( i ) . getFileName ( ) ) ;
// # endif
pDir . setFileList ( pMergedInfo . get ( ) ) ; return pDir ; }


signature:
public class CppAssetManager { /** * Scan the contents of the specified directory and merge them into the
 * " pMergedInfo " vector , removing previous entries if we find " exclude "
 * directives .
 * Returns " false " if we found nothing to contribute . */
boolean scanAndMergeDirLocked ( Ref < SortedVector < AssetDir . FileInfo > > pMergedInfoRef , final asset_path ap , final String rootDir , final String dirName ) { } }

implementation:
SortedVector < AssetDir . FileInfo > pMergedInfo = pMergedInfoRef . get ( ) ; assert ( pMergedInfo != null ) ; // printf ( " scanAndMergeDir : % s % s % s \ n " , ap . path . string ( ) , rootDir , dirName ) ;
String8 path = createPathNameLocked ( ap , rootDir ) ; if ( dirName . charAt ( 0 ) != '\0' ) { path . appendPath ( dirName ) ; } SortedVector < AssetDir . FileInfo > pContents = scanDirLocked ( path ) ; if ( pContents == null ) { return false ; } // if we wanted to do an incremental cache fill , we would do it here
/* * Process " exclude " directives . If we find a filename that ends with
 * " . EXCLUDE " , we look for a matching entry in the " merged " set , and
 * remove it if we find it . We also delete the " exclude " entry . */
int i , count , exclExtLen ; count = pContents . size ( ) ; exclExtLen = kExcludeExtension . length ( ) ; for ( i = 0 ; i < count ; i ++ ) { final String name ; int nameLen ; name = pContents . itemAt ( i ) . getFileName ( ) . string ( ) ; nameLen = name . length ( ) ; if ( name . endsWith ( kExcludeExtension ) ) { String8 match = new String8 ( name , nameLen - exclExtLen ) ; int matchIdx ; matchIdx = AssetDir . FileInfo . findEntry ( pMergedInfo , match ) ; if ( matchIdx > 0 ) { ALOGV ( "Excluding '%s' [%s]\n" , pMergedInfo . itemAt ( matchIdx ) . getFileName ( ) . string ( ) , pMergedInfo . itemAt ( matchIdx ) . getSourceName ( ) . string ( ) ) ; pMergedInfo . removeAt ( matchIdx ) ; } else { // printf ( " + + + no match on ' % s ' \ n " , ( final char * ) match ) ;
} ALOGD ( "HEY: size=%d removing %d\n" , ( int ) pContents . size ( ) , i ) ; pContents . removeAt ( i ) ; i -- ; // adjust " for " loop
count -- ; // and loop limit
} } mergeInfoLocked ( pMergedInfoRef , pContents ) ; return true ;


signature:
public class CppAssetManager { /** * Scan the contents of the specified directory , and stuff what we find
 * into a newly - allocated vector .
 * Files ending in " . gz " will have their extensions removed .
 * We should probably think about skipping files with " illegal " names ,
 * e . g . illegal characters ( / \ : ) or excessive length .
 * Returns null if the specified directory doesn ' t exist . */
SortedVector < AssetDir . FileInfo > scanDirLocked ( final String8 path ) { } }

implementation:
String8 pathCopy = new String8 ( path ) ; SortedVector < AssetDir . FileInfo > pContents = null ; // DIR * dir ;
File dir ; FileType fileType ; ALOGV ( "Scanning dir '%s'\n" , path . string ( ) ) ; dir = new File ( path . string ( ) ) ; if ( ! dir . exists ( ) ) { return null ; } pContents = new SortedVector < > ( ) ; for ( File entry : dir . listFiles ( ) ) { if ( entry == null ) { break ; } // if ( strcmp ( entry . d _ name , " . " ) = = 0 | |
// strcmp ( entry . d _ name , " . . " ) = = 0)
// continue ;
// # ifdef _ DIRENT _ HAVE _ D _ TYPE
// if ( entry . d _ type = = DT _ REG )
// fileType = kFileTypeRegular ;
// else if ( entry . d _ type = = DT _ DIR )
// fileType = kFileTypeDirectory ;
// else
// fileType = kFileTypeUnknown ;
// # else
// stat the file
fileType = getFileType ( pathCopy . appendPath ( entry . getName ( ) ) . string ( ) ) ; // # endif
if ( fileType != FileType . kFileTypeRegular && fileType != kFileTypeDirectory ) { continue ; } AssetDir . FileInfo info = new AssetDir . FileInfo ( ) ; info . set ( new String8 ( entry . getName ( ) ) , fileType ) ; if ( info . getFileName ( ) . getPathExtension ( ) . equalsIgnoreCase ( ".gz" ) ) { info . setFileName ( info . getFileName ( ) . getBasePath ( ) ) ; } info . setSourceName ( pathCopy . appendPath ( info . getFileName ( ) . string ( ) ) ) ; pContents . add ( info ) ; } return pContents ;


signature:
public class CppAssetManager { /** * Scan the contents out of the specified Zip archive , and merge what we
 * find into " pMergedInfo " . If the Zip archive in question doesn ' t exist ,
 * we return immediately .
 * Returns " false " if we found nothing to contribute . */
boolean scanAndMergeZipLocked ( Ref < SortedVector < AssetDir . FileInfo > > pMergedInfo , final asset_path ap , final String rootDir , final String baseDirName ) { } }

implementation:
ZipFileRO pZip ; List < String8 > dirs = new ArrayList < > ( ) ; // AssetDir . FileInfo info = new FileInfo ( ) ;
SortedVector < AssetDir . FileInfo > contents = new SortedVector < > ( ) ; String8 sourceName ; String8 zipName ; String8 dirName = new String8 ( ) ; pZip = mZipSet . getZip ( ap . path . string ( ) ) ; if ( pZip == null ) { ALOGW ( "Failure opening zip %s\n" , ap . path . string ( ) ) ; return false ; } zipName = ZipSet . getPathName ( ap . path . string ( ) ) ; /* convert " sounds " to " rootDir / sounds " */
if ( rootDir != null ) { dirName = new String8 ( rootDir ) ; } dirName . appendPath ( baseDirName ) ; /* * Scan through the list of files , looking for a match . The files in
 * the Zip table of contents are not in sorted order , so we have to
 * process the entire list . We ' re looking for a string that begins
 * with the characters in " dirName " , is followed by a ' / ' , and has no
 * subsequent ' / ' in the stuff that follows .
 * What makes this especially fun is that directories are not stored
 * explicitly in Zip archives , so we have to infer them from context .
 * When we see " sounds / foo . wav " we have to leave a note to ourselves
 * to insert a directory called " sounds " into the list . We store
 * these in temporary vector so that we only return each one once .
 * Name comparisons are case - sensitive to match UNIX filesystem
 * semantics . */
int dirNameLen = dirName . length ( ) ; final Ref < Enumeration < ? extends ZipEntry > > iterationCookie = new Ref < > ( null ) ; if ( ! pZip . startIteration ( iterationCookie , dirName . string ( ) , null ) ) { ALOGW ( "ZipFileRO.startIteration returned false" ) ; return false ; } ZipEntryRO entry ; while ( ( entry = pZip . nextEntry ( iterationCookie . get ( ) ) ) != null ) { final Ref < String > nameBuf = new Ref < > ( null ) ; if ( pZip . getEntryFileName ( entry , nameBuf ) != 0 ) { // TODO : fix this if we expect to have long names
ALOGE ( "ARGH: name too long?\n" ) ; continue ; } // System . out . printf ( " Comparing % s in % s ? \ n " , nameBuf . get ( ) , dirName . string ( ) ) ;
if ( ! nameBuf . get ( ) . startsWith ( dirName . string ( ) + '/' ) ) { // not matching
continue ; } if ( dirNameLen == 0 || nameBuf . get ( ) . charAt ( dirNameLen ) == '/' ) { int cp = 0 ; int nextSlashIndex ; // cp = nameBuf + dirNameLen ;
cp += dirNameLen ; if ( dirNameLen != 0 ) { cp ++ ; // advance past the ' / '
} nextSlashIndex = nameBuf . get ( ) . indexOf ( '/' , cp ) ; // xxx this may break if there are bare directory entries
if ( nextSlashIndex == - 1 ) { /* this is a file in the requested directory */
String8 fileName = new String8 ( nameBuf . get ( ) ) . getPathLeaf ( ) ; if ( fileName . string ( ) . isEmpty ( ) ) { // ignore
continue ; } AssetDir . FileInfo info = new FileInfo ( ) ; info . set ( fileName , FileType . kFileTypeRegular ) ; info . setSourceName ( createZipSourceNameLocked ( zipName , dirName , info . getFileName ( ) ) ) ; contents . add ( info ) ; // printf ( " FOUND : file ' % s ' \ n " , info . getFileName ( ) . string ( ) ) ;
} else { /* this is a subdir ; add it if we don ' t already have it */
String8 subdirName = new String8 ( nameBuf . get ( ) . substring ( cp , nextSlashIndex ) ) ; int j ; int N = dirs . size ( ) ; for ( j = 0 ; j < N ; j ++ ) { if ( subdirName . equals ( dirs . get ( j ) ) ) { break ; } } if ( j == N ) { dirs . add ( subdirName ) ; } // printf ( " FOUND : dir ' % s ' \ n " , subdirName . string ( ) ) ;
} } } pZip . endIteration ( iterationCookie ) ; /* * Add the set of unique directories . */
for ( int i = 0 ; i < dirs . size ( ) ; i ++ ) { AssetDir . FileInfo info = new FileInfo ( ) ; info . set ( dirs . get ( i ) , kFileTypeDirectory ) ; info . setSourceName ( createZipSourceNameLocked ( zipName , dirName , info . getFileName ( ) ) ) ; contents . add ( info ) ; } mergeInfoLocked ( pMergedInfo , contents ) ; return true ;


signature:
public class CppAssetManager { /** * Merge two vectors of FileInfo .
 * The merged contents will be stuffed into * pMergedInfo .
 * If an entry for a file exists in both " pMergedInfo " and " pContents " ,
 * we use the newer " pContents " entry . */
void mergeInfoLocked ( Ref < SortedVector < AssetDir . FileInfo > > pMergedInfoRef , final SortedVector < AssetDir . FileInfo > pContents ) { } }

implementation:
/* * Merge what we found in this directory with what we found in
 * other places .
 * Two basic approaches :
 * ( 1 ) Create a new array that holds the unique values of the two
 * arrays .
 * ( 2 ) Take the elements from pContents and shove them into pMergedInfo .
 * Because these are vectors of complex objects , moving elements around
 * inside the vector requires finalructing new objects and allocating
 * storage for members . With approach # 1 , we ' re always adding to the
 * end , whereas with # 2 we could be inserting multiple elements at the
 * front of the vector . Approach # 1 requires a full copy of the
 * contents of pMergedInfo , but approach # 2 requires the same copy for
 * every insertion at the front of pMergedInfo .
 * ( We should probably use a SortedVector interface that allows us to
 * just stuff items in , trusting us to maintain the sort order . ) */
SortedVector < AssetDir . FileInfo > pNewSorted ; int mergeMax , contMax ; int mergeIdx , contIdx ; SortedVector < AssetDir . FileInfo > pMergedInfo = pMergedInfoRef . get ( ) ; pNewSorted = new SortedVector < > ( ) ; mergeMax = pMergedInfo . size ( ) ; contMax = pContents . size ( ) ; mergeIdx = contIdx = 0 ; while ( mergeIdx < mergeMax || contIdx < contMax ) { if ( mergeIdx == mergeMax ) { /* hit end of " merge " list , copy rest of " contents " */
pNewSorted . add ( pContents . itemAt ( contIdx ) ) ; contIdx ++ ; } else if ( contIdx == contMax ) { /* hit end of " cont " list , copy rest of " merge " */
pNewSorted . add ( pMergedInfo . itemAt ( mergeIdx ) ) ; mergeIdx ++ ; } else if ( pMergedInfo . itemAt ( mergeIdx ) == pContents . itemAt ( contIdx ) ) { /* items are identical , add newer and advance both indices */
pNewSorted . add ( pContents . itemAt ( contIdx ) ) ; mergeIdx ++ ; contIdx ++ ; } else if ( pMergedInfo . itemAt ( mergeIdx ) . isLessThan ( pContents . itemAt ( contIdx ) ) ) { /* " merge " is lower , add that one */
pNewSorted . add ( pMergedInfo . itemAt ( mergeIdx ) ) ; mergeIdx ++ ; } else { /* " cont " is lower , add that one */
assert ( pContents . itemAt ( contIdx ) . isLessThan ( pMergedInfo . itemAt ( mergeIdx ) ) ) ; pNewSorted . add ( pContents . itemAt ( contIdx ) ) ; contIdx ++ ; } } /* * Overwrite the " merged " list with the new stuff . */
pMergedInfoRef . set ( pNewSorted ) ; // # if 0 / / for Vector , rather than SortedVector
// int i , j ;
// for ( i = pContents . size ( ) - 1 ; i > = 0 ; i - - ) {
// boolean add = true ;
// for ( j = pMergedInfo . size ( ) - 1 ; j > = 0 ; j - - ) {
// / * case - sensitive comparisons , to behave like UNIX fs * /
// if ( strcmp ( pContents . itemAt ( i ) . mFileName ,
// pMergedInfo . itemAt ( j ) . mFileName ) = = 0)
// / * match , don ' t add this entry * /
// add = false ;
// break ;
// if ( add )
// pMergedInfo . add ( pContents . itemAt ( i ) ) ;
// # endif


signature:
public class FileMap { /** * Returns " false " on failure . */
boolean create ( String origFileName , int fd , long offset , int length , boolean readOnly ) { } }

implementation: this . mFileName = origFileName ; this . fd = fd ; this . mDataOffset = offset ; this . readOnly = readOnly ; return true ;


signature: public class FileMap { public boolean createFromZip ( String origFileName , ZipFile zipFile , ZipEntry entry , int length , boolean readOnly ) { } }

implementation:
isFromZip = true ; this . zipFile = zipFile ; this . zipEntry = entry ; int prot , flags , adjust ; long adjOffset ; int adjLength ; int ptr ; long offset = guessOffsetFor ( zipFile , entry ) ; assert ( fd >= 0 ) ; assert ( offset >= 0 ) ; // assert ( length > 0 ) ;
// init on first use
// if ( mPageSize = = - 1 ) {
// mPageSize = sysconf ( _ SC _ PAGESIZE ) ;
// if ( mPageSize = = - 1 ) {
// ALOGE ( " could not get _ SC _ PAGESIZE \ n " ) ;
// return false ;
// adjust = Math . toIntExact ( offset % mPageSize ) ;
// adjOffset = offset - adjust ;
// adjLength = length + adjust ;
// flags = MAP _ SHARED ;
// prot = PROT _ READ ;
// if ( ! readOnly )
// prot | = PROT _ WRITE ;
// ptr = mmap ( null , adjLength , prot , flags , fd , adjOffset ) ;
// if ( ptr = = MAP _ FAILED ) {
// ALOGE ( " mmap ( % lld , 0x % x ) failed : % s \ n " ,
// ( long long ) adjOffset , adjLength , strerror ( errno ) ) ;
// return false ;
// mBasePtr = ptr ;
mFileName = origFileName != null ? origFileName : null ; // mBaseLength = adjLength ;
mDataOffset = offset ; // mDataPtr = mBasePtr + adjust ;
mDataLength = toIntExact ( entry . getSize ( ) ) ; // assert ( mBasePtr ! = 0 ) ;
ALOGV ( "MAP: base %s/0x%x data %s/0x%x\n" , mBasePtr , mBaseLength , mDataPtr , mDataLength ) ; return true ;


signature:
public class FileMap { /** * Get a pointer to the piece of the file we requested . */
synchronized byte [ ] getDataPtr ( ) { } }

implementation: if ( mDataPtr == null ) { mDataPtr = new byte [ mDataLength ] ; InputStream is ; try { if ( isFromZip ) { is = zipFile . getInputStream ( zipEntry ) ; } else { is = new FileInputStream ( getFileName ( ) ) ; } try { readFully ( is , mDataPtr ) ; } finally { is . close ( ) ; } } catch ( IOException e ) { throw new RuntimeException ( e ) ; } } return mDataPtr ;


signature:
public class PausedExecutorService { /** * Execute all posted tasks and block until they are complete .
 * @ return the number of tasks executed */
public int runAll ( ) { } }

implementation: int numTasksRun = 0 ; if ( Thread . currentThread ( ) . equals ( executorThread ) ) { Logger . info ( "ignoring request to execute task - called from executor's own thread" ) ; return numTasksRun ; } while ( hasQueuedTasks ( ) ) { runNext ( ) ; numTasksRun ++ ; } return numTasksRun ;


signature:
public class PausedExecutorService { /** * Executes the next queued task .
 * Will be ignored if called from the executor service thread to prevent deadlocks .
 * @ return true if task was run , false if queue was empty */
public boolean runNext ( ) { } }

implementation: if ( ! hasQueuedTasks ( ) ) { return false ; } if ( Thread . currentThread ( ) . equals ( executorThread ) ) { Logger . info ( "ignoring request to execute task - called from executor's own thread" ) ; return false ; } Runnable task = deferredTasks . poll ( ) ; task . run ( ) ; return true ;


signature:
public class ConfigDescription { /** * transliterated from https : / / android . googlesource . com / platform / frameworks / base / + / android - 9.0.0 _ r12 / tools / aapt / AaptConfig . cpp */
private static void applyVersionForCompatibility ( ResTable_config config ) { } }

implementation: if ( config == null ) { return ; } int min_sdk = 0 ; if ( ( ( config . uiMode & ResTable_config . MASK_UI_MODE_TYPE ) == ResTable_config . UI_MODE_TYPE_VR_HEADSET ) || ( config . colorMode & ResTable_config . MASK_WIDE_COLOR_GAMUT ) != 0 || ( config . colorMode & ResTable_config . MASK_HDR ) != 0 ) { min_sdk = SDK_O ; } else if ( isTruthy ( config . screenLayout2 & ResTable_config . MASK_SCREENROUND ) ) { min_sdk = SDK_MNC ; } else if ( config . density == ResTable_config . DENSITY_ANY ) { min_sdk = SDK_LOLLIPOP ; } else if ( config . smallestScreenWidthDp != ResTable_config . SCREENWIDTH_ANY || config . screenWidthDp != ResTable_config . SCREENWIDTH_ANY || config . screenHeightDp != ResTable_config . SCREENHEIGHT_ANY ) { min_sdk = SDK_HONEYCOMB_MR2 ; } else if ( ( config . uiMode & ResTable_config . MASK_UI_MODE_TYPE ) != ResTable_config . UI_MODE_TYPE_ANY || ( config . uiMode & ResTable_config . MASK_UI_MODE_NIGHT ) != ResTable_config . UI_MODE_NIGHT_ANY ) { min_sdk = SDK_FROYO ; } else if ( ( config . screenLayout & ResTable_config . MASK_SCREENSIZE ) != ResTable_config . SCREENSIZE_ANY || ( config . screenLayout & ResTable_config . MASK_SCREENLONG ) != ResTable_config . SCREENLONG_ANY || config . density != ResTable_config . DENSITY_DEFAULT ) { min_sdk = SDK_DONUT ; } if ( min_sdk > config . sdkVersion ) { config . sdkVersion = min_sdk ; }


signature:
public class ShadowMessage { /** * Resets the static state of the { @ link Message } class by
 * emptying the message pool . */
@ Resetter public static void reset ( ) { } }

implementation: Object lock = reflector ( ReflectorMessage . class ) . getPoolSync ( ) ; synchronized ( lock ) { reflector ( ReflectorMessage . class ) . setPoolSize ( 0 ) ; reflector ( ReflectorMessage . class ) . setPool ( null ) ; }


signature:
public class ShadowAudioManager { /** * Provides a mock like interface for the requestAudioFocus method by storing the request object
 * for later inspection and returning the value specified in setNextFocusRequestResponse . */
@ Implementation ( minSdk = O ) protected int requestAudioFocus ( android . media . AudioFocusRequest audioFocusRequest ) { } }

implementation: lastAudioFocusRequest = new AudioFocusRequest ( audioFocusRequest ) ; return nextResponseValue ;


signature:
public class ShadowAudioManager { /** * Provides a mock like interface for the abandonAudioFocusRequest method by storing the request
 * object for later inspection and returning the value specified in setNextFocusRequestResponse . */
@ Implementation ( minSdk = O ) protected int abandonAudioFocusRequest ( android . media . AudioFocusRequest audioFocusRequest ) { } }

implementation: lastAbandonedAudioFocusRequest = audioFocusRequest ; return nextResponseValue ;


signature:
public class ShadowAudioManager { /** * Implements { @ link AudioManager # adjustStreamVolume ( int , int , int ) } .
 * < p > Currently supports only the directions { @ link AudioManager # ADJUST _ MUTE } and { @ link
 * AudioManager # ADJUST _ UNMUTE } . */
@ Implementation protected void adjustStreamVolume ( int streamType , int direction , int flags ) { } }

implementation: switch ( direction ) { case AudioManager . ADJUST_MUTE : streamsMuteState . put ( streamType , true ) ; break ; case AudioManager . ADJUST_UNMUTE : streamsMuteState . put ( streamType , false ) ; break ; default : break ; }


signature:
public class ShadowAudioManager { /** * Sets active playback configurations that will be served by { @ link
 * AudioManager # getActivePlaybackConfigurations } .
 * < p > Note that there is no public { @ link AudioPlaybackConfiguration } constructor , so the
 * configurations returned are specified by their audio attributes only . */
@ TargetApi ( VERSION_CODES . O ) public void setActivePlaybackConfigurationsFor ( List < AudioAttributes > audioAttributes ) { } }

implementation:
activePlaybackConfigurations = new ArrayList < > ( audioAttributes . size ( ) ) ; for ( AudioAttributes audioAttribute : audioAttributes ) { Parcel p = Parcel . obtain ( ) ; p . writeInt ( 0 ) ; // mPlayerIId
p . writeInt ( 0 ) ; // mPlayerType
p . writeInt ( 0 ) ; // mClientUid
p . writeInt ( 0 ) ; // mClientPid
p . writeInt ( AudioPlaybackConfiguration . PLAYER_STATE_STARTED ) ; // mPlayerState
audioAttribute . writeToParcel ( p , 0 ) ; p . writeStrongInterface ( null ) ; byte [ ] bytes = p . marshall ( ) ; p . recycle ( ) ; p = Parcel . obtain ( ) ; p . unmarshall ( bytes , 0 , bytes . length ) ; p . setDataPosition ( 0 ) ; AudioPlaybackConfiguration configuration = AudioPlaybackConfiguration . CREATOR . createFromParcel ( p ) ; p . recycle ( ) ; activePlaybackConfigurations . add ( configuration ) ; }


signature:
public class ShadowMediaCodec { /** * Starts the async encoding process , by first reporting a format change event , and then
 * presenting an input buffer to the callback . */
@ Implementation ( minSdk = LOLLIPOP ) protected void native_start ( ) { } }

implementation:
// Currently only support async - mode .
if ( callback == null ) { return ; } // Report the format as changed , to simulate adding codec specific info before making input
// buffers available .
HashMap < String , Object > format = new HashMap < > ( ) ; format . put ( "csd-0" , ByteBuffer . wrap ( new byte [ ] { 0x13 , 0x10 } ) ) ; format . put ( "csd-1" , ByteBuffer . wrap ( new byte [ 0 ] ) ) ; postFakeNativeEvent ( EVENT_CALLBACK , CB_OUTPUT_FORMAT_CHANGE , 0 , format ) ; // Reset state .
reachedEos = false ; makeInputBufferAvailable ( 0 ) ;


signature:
public class ShadowMediaCodec { /** * Returns the input or output buffer corresponding to the given index , or null if invalid . */
@ Implementation ( minSdk = LOLLIPOP ) protected ByteBuffer getBuffer ( boolean input , int index ) { } }

implementation: ByteBuffer [ ] buffers = input ? inputBuffers : outputBuffers ; return ( index >= 0 && index < buffers . length ) ? buffers [ index ] : null ;


signature:
public class ShadowMediaCodec { /** * Triggers presentation of the corresponding output buffer for the given input buffer , and passes
 * the given metadata as buffer info . */
@ Implementation ( minSdk = LOLLIPOP ) protected void native_queueInputBuffer ( int index , int offset , int size , long presentationTimeUs , int flags ) { } }

implementation:
// Check if this should be the last buffer cycle .
if ( ( flags & MediaCodec . BUFFER_FLAG_END_OF_STREAM ) != 0 ) { reachedEos = true ; } BufferInfo info = new BufferInfo ( ) ; info . set ( offset , size , presentationTimeUs , flags ) ; makeOutputBufferAvailable ( index , info ) ;


signature:
public class ShadowMediaCodec { /** * Triggers presentation of the corresponding input buffer for the given output buffer , if end of
 * stream has not yet been signaled . */
@ Implementation ( minSdk = LOLLIPOP ) protected void releaseOutputBuffer ( int index , boolean render , boolean updatePTS , long timeNs ) { } }

implementation: if ( reachedEos ) { return ; } makeInputBufferAvailable ( index ) ;


signature:
public class ShadowMediaCodec { /** * Prevents calling Android - only methods on basic ByteBuffer objects . Replicates existing behavior
 * adjusting buffer positions and limits . */
@ Implementation ( minSdk = LOLLIPOP ) protected void validateOutputByteBuffer ( @ Nullable ByteBuffer [ ] buffers , int index , @ NonNull BufferInfo info ) { } }

implementation: if ( buffers != null && index >= 0 && index < buffers . length ) { ByteBuffer buffer = buffers [ index ] ; if ( buffer != null ) { buffer . limit ( info . offset + info . size ) . position ( info . offset ) ; } }


signature: public class ResourceUtils { static boolean ExtractResourceName ( String str , Ref < String > out_package , Ref < String > out_type , final Ref < String > out_entry ) { } }

implementation: out_package . set ( "" ) ; out_type . set ( "" ) ; boolean has_package_separator = false ; boolean has_type_separator = false ; int start = 0 ; int end = start + str . length ( ) ; int current = start ; while ( current != end ) { if ( out_type . get ( ) . length ( ) == 0 && str . charAt ( current ) == '/' ) { has_type_separator = true ; out_type . set ( str . substring ( start , current ) ) ; start = current + 1 ; } else if ( out_package . get ( ) . length ( ) == 0 && str . charAt ( current ) == ':' ) { has_package_separator = true ; out_package . set ( str . substring ( start , current ) ) ; start = current + 1 ; } current ++ ; } out_entry . set ( str . substring ( start , end ) ) ; return ! ( has_package_separator && out_package . get ( ) . isEmpty ( ) ) && ! ( has_type_separator && out_type . get ( ) . isEmpty ( ) ) ;


signature:
public class ShadowUsageStatsManager { /** * Adds an event to be returned by { @ link UsageStatsManager # queryEvents } .
 * < p > This method won ' t affect the results of { @ link # queryUsageStats } method .
 * @ deprecated Use { @ link # addEvent ( Event ) } and { @ link EventBuilder } instead . */
@ Deprecated public void addEvent ( String packageName , long timeStamp , int eventType ) { } }

implementation: EventBuilder eventBuilder = EventBuilder . buildEvent ( ) . setPackage ( packageName ) . setTimeStamp ( timeStamp ) . setEventType ( eventType ) ; if ( eventType == Event . CONFIGURATION_CHANGE ) { eventBuilder . setConfiguration ( new Configuration ( ) ) ; } addEvent ( eventBuilder . build ( ) ) ;


signature:
public class ShadowUsageStatsManager { /** * Simulates the operations done by the framework when there is a time change . If the time is
 * changed , the timestamps of all existing usage events will be shifted by the same offset as the
 * time change , in order to make sure they remain stable relative to the new time .
 * < p > This method won ' t affect the results of { @ link # queryUsageStats } method .
 * @ param offsetToAddInMillis the offset to be applied to all events . For example , if { @ code
 * offsetInMillis } is 60,000 , then all { @ link Event } s will be shifted forward by 1 minute
 * ( into the future ) . Likewise , if { @ code offsetInMillis } is - 60,000 , then all { @ link Event } s
 * will be shifted backward by 1 minute ( into the past ) . */
public void simulateTimeChange ( long offsetToAddInMillis ) { } }

implementation: ImmutableMap . Builder < Long , Event > eventMapBuilder = ImmutableMap . builder ( ) ; for ( Event event : eventsByTimeStamp . values ( ) ) { long newTimestamp = event . getTimeStamp ( ) + offsetToAddInMillis ; eventMapBuilder . put ( newTimestamp , EventBuilder . fromEvent ( event ) . setTimeStamp ( newTimestamp ) . build ( ) ) ; } eventsByTimeStamp . putAll ( eventMapBuilder . build ( ) ) ;


signature:
public class ShadowUsageStatsManager { /** * Returns aggregated UsageStats added by calling { @ link # addUsageStats } .
 * < p > The real implementation creates these aggregated objects from individual { @ link Event } . This
 * aggregation logic is nontrivial , so the shadow implementation just returns the aggregate data
 * added using { @ link # addUsageStats } . */
@ Implementation protected List < UsageStats > queryUsageStats ( int intervalType , long beginTime , long endTime ) { } }

implementation: List < UsageStats > results = new ArrayList < > ( ) ; Range < Long > queryRange = Range . closed ( beginTime , endTime ) ; for ( UsageStats stats : usageStatsByIntervalType . get ( intervalType ) ) { Range < Long > statsRange = Range . closed ( stats . getFirstTimeStamp ( ) , stats . getLastTimeStamp ( ) ) ; if ( queryRange . isConnected ( statsRange ) ) { results . add ( stats ) ; } } return results ;


signature:
public class ShadowUsageStatsManager { /** * Returns the current standby bucket of the specified app that is set by { @ code
 * setAppStandbyBucket } . If the standby bucket value has never been set , return { @ link
 * UsageStatsManager . STANDBY _ BUCKET _ ACTIVE } . */
@ Implementation ( minSdk = Build . VERSION_CODES . P ) @ HiddenApi public @ StandbyBuckets int getAppStandbyBucket ( String packageName ) { } }

implementation: Integer bucket = appStandbyBuckets . get ( packageName ) ; return ( bucket == null ) ? UsageStatsManager . STANDBY_BUCKET_ACTIVE : bucket ;


signature:
public class ShadowUsageStatsManager { /** * Sets the standby bucket of the specified app . */
@ Implementation ( minSdk = Build . VERSION_CODES . P ) @ HiddenApi public void setAppStandbyBucket ( String packageName , @ StandbyBuckets int bucket ) { } }

implementation: appStandbyBuckets . put ( packageName , bucket ) ;


signature:
public class ShadowUsageStatsManager { /** * Triggers a currently registered { @ link AppUsageObserver } with { @ code observerId } .
 * < p > The observer will be no longer registered afterwards . */
public void triggerRegisteredAppUsageObserver ( int observerId , long timeUsedInMillis ) { } }

implementation: AppUsageObserver observer = appUsageObserversById . remove ( observerId ) ; long timeLimitInMillis = observer . timeUnit . toMillis ( observer . timeLimit ) ; Intent intent = new Intent ( ) . putExtra ( UsageStatsManager . EXTRA_OBSERVER_ID , observerId ) . putExtra ( UsageStatsManager . EXTRA_TIME_LIMIT , timeLimitInMillis ) . putExtra ( UsageStatsManager . EXTRA_TIME_USED , timeUsedInMillis ) ; try { observer . callbackIntent . send ( RuntimeEnvironment . application , 0 , intent ) ; } catch ( CanceledException e ) { throw new RuntimeException ( e ) ; }


signature:
public class ShadowUsageStatsManager { /** * Triggers a currently registered { @ link UsageSessionObserver } with { @ code observerId } .
 * < p > The observer SHOULD be registered afterwards . */
public void triggerRegisteredSessionStepObserver ( int observerId , long timeUsedInMillis ) { } }

implementation: UsageSessionObserver observer = usageSessionObserversById . get ( observerId ) ; long sessionStepTimeInMillis = observer . sessionStepDuration . toMillis ( ) ; Intent intent = new Intent ( ) . putExtra ( UsageStatsManager . EXTRA_OBSERVER_ID , observerId ) . putExtra ( UsageStatsManager . EXTRA_TIME_LIMIT , sessionStepTimeInMillis ) . putExtra ( UsageStatsManager . EXTRA_TIME_USED , timeUsedInMillis ) ; try { observer . sessionStepTriggeredIntent . send ( RuntimeEnvironment . application , 0 , intent ) ; } catch ( CanceledException e ) { throw new RuntimeException ( e ) ; }


signature:
public class ShadowUsageStatsManager { /** * Triggers a currently registered { @ link UsageSessionObserver } with { @ code observerId } .
 * < p > The observer SHOULD be registered afterwards . */
public void triggerRegisteredSessionEndedObserver ( int observerId ) { } }

implementation: UsageSessionObserver observer = usageSessionObserversById . get ( observerId ) ; Intent intent = new Intent ( ) . putExtra ( UsageStatsManager . EXTRA_OBSERVER_ID , observerId ) ; try { observer . sessionEndedIntent . send ( RuntimeEnvironment . application , 0 , intent ) ; } catch ( CanceledException e ) { throw new RuntimeException ( e ) ; }


signature:
public class ShadowBluetoothHeadset { /** * Overrides behavior of { @ link getConnectionState } .
 * @ return { @ code BluetoothProfile . STATE _ CONNECTED } if the given device has been previously added
 * by a call to { @ link ShadowBluetoothHeadset # addConnectedDevice } , and { @ code
 * BluetoothProfile . STATE _ DISCONNECTED } otherwise . */
@ Implementation protected int getConnectionState ( BluetoothDevice device ) { } }

implementation: return connectedDevices . contains ( device ) ? BluetoothProfile . STATE_CONNECTED : BluetoothProfile . STATE_DISCONNECTED ;


signature:
public class ShadowBluetoothHeadset { /** * Overrides behavior of { @ link sendVendorSpecificResultCode } .
 * @ return ' true ' only if the given device has been previously added by a call to { @ link
 * ShadowBluetoothHeadset # addConnectedDevice } and { @ link
 * ShadowBluetoothHeadset # setAllowsSendVendorSpecificResultCode } has not been called with
 * ' false ' argument .
 * @ throws IllegalArgumentException if ' command ' argument is null , per Android API */
@ Implementation ( minSdk = KITKAT ) protected boolean sendVendorSpecificResultCode ( BluetoothDevice device , String command , String arg ) { } }

implementation: if ( command == null ) { throw new IllegalArgumentException ( "Command cannot be null" ) ; } return allowsSendVendorSpecificResultCode && connectedDevices . contains ( device ) ;


signature:
public class LegacyManifestParser { /** * Goes through the meta data and puts each value in to a bundle as the correct type .
 * < p > Note that this will convert resource identifiers specified via the value attribute as well .
 * @ param meta Meta data to put in to a bundle
 * @ return bundle containing the meta data */
private static Bundle metaDataToBundle ( Map < String , Object > meta ) { } }

implementation: if ( meta . size ( ) == 0 ) { return null ; } Bundle bundle = new Bundle ( ) ; for ( Map . Entry < String , Object > entry : meta . entrySet ( ) ) { String key = entry . getKey ( ) ; Object value = entry . getValue ( ) ; if ( Boolean . class . isInstance ( value ) ) { bundle . putBoolean ( key , ( Boolean ) value ) ; } else if ( Float . class . isInstance ( value ) ) { bundle . putFloat ( key , ( Float ) value ) ; } else if ( Integer . class . isInstance ( value ) ) { bundle . putInt ( key , ( Integer ) value ) ; } else { bundle . putString ( key , value == null ? null : value . toString ( ) ) ; } } return bundle ;


signature:
public class Logger { /** * Log an error message .
 * @ param message Message text .
 * @ param e The exception . */
public static void error ( String message , Throwable e ) { } }

implementation: System . err . print ( "ERROR: " ) ; System . err . println ( message ) ; e . printStackTrace ( ) ;


signature:
public class Logger { /** * Log an error message .
 * @ param message Message text .
 * @ param args Message arguments . */
public static void error ( String message , Object ... args ) { } }

implementation: System . err . print ( "ERROR: " ) ; System . err . println ( String . format ( message , args ) ) ;


signature:
public class ShadowSQLiteConnection { /** * Convert SQL with phrase COLLATE LOCALIZED or COLLATE UNICODE to COLLATE NOCASE . */
static String convertSQLWithLocalizedUnicodeCollator ( String sql ) { } }

implementation: Matcher matcher = COLLATE_LOCALIZED_UNICODE_PATTERN . matcher ( sql ) ; return matcher . replaceAll ( " COLLATE NOCASE" ) ;


signature:
public class ShadowMediaMetadataRetriever { /** * Adds the given keyCode / value pair for the given data source .
 * Uses < tt > path < / tt > to call { @ link org . robolectric . shadows . util . DataSource # toDataSource ( String ) } and
 * then calls { @ link # addMetadata ( DataSource , int , String ) } . This
 * method is retained mostly for backwards compatibility ;
 * you can call { @ link # addMetadata ( DataSource , int , String ) } directly .
 * @ param path the path to the data source whose metadata is being set .
 * @ param keyCode the keyCode for the metadata being set , as used by { @ link MediaMetadataRetriever # extractMetadata ( int ) } .
 * @ param value the value for the specified metadata . */
public static void addMetadata ( String path , int keyCode , String value ) { } }

implementation: addMetadata ( toDataSource ( path ) , keyCode , value ) ;


signature:
public class ShadowMediaMetadataRetriever { /** * Adds the given bitmap at the given time for the given data source .
 * Uses < tt > path < / tt > to call { @ link org . robolectric . shadows . util . DataSource # toDataSource ( String ) } and
 * then calls { @ link # addFrame ( DataSource , long , Bitmap ) } . This
 * method is retained mostly for backwards compatibility ;
 * you can call { @ link # addFrame ( DataSource , long , Bitmap ) } directly .
 * @ param path the path to the data source .
 * @ param time the playback time at which the specified bitmap
 * should be retrieved .
 * @ param bitmap the bitmap to retrieve . */
public static void addFrame ( String path , long time , Bitmap bitmap ) { } }

implementation: addFrame ( toDataSource ( path ) , time , bitmap ) ;


signature:
public class ShadowMediaMetadataRetriever { /** * Adds the given bitmap at the given time for the given data source .
 * Uses < tt > path < / tt > to call { @ link org . robolectric . shadows . util . DataSource # toDataSource ( Context , Uri ) } and
 * then calls { @ link # addFrame ( DataSource , long , Bitmap ) } . This
 * method is retained mostly for backwards compatibility ;
 * you can call { @ link # addFrame ( DataSource , long , Bitmap ) } directly .
 * @ param context the Context object to match on the data source .
 * @ param uri the Uri of the data source .
 * @ param time the playback time at which the specified bitmap
 * should be retrieved .
 * @ param bitmap the bitmap to retrieve . */
public static void addFrame ( Context context , Uri uri , long time , Bitmap bitmap ) { } }

implementation: addFrame ( toDataSource ( context , uri ) , time , bitmap ) ;


signature:
public class ShadowMediaMetadataRetriever { /** * Adds the given bitmap at the given time for the given data source .
 * Uses < tt > path < / tt > to call { @ link org . robolectric . shadows . util . DataSource # toDataSource ( String , Map ) } and
 * then calls { @ link # addFrame ( DataSource , long , Bitmap ) } . This
 * method is retained mostly for backwards compatibility ;
 * you can call { @ link # addFrame ( DataSource , long , Bitmap ) } directly .
 * @ param uri the Uri of the data source .
 * @ param headers the headers to use when requesting the specified uri .
 * @ param time the playback time at which the specified bitmap
 * should be retrieved .
 * @ param bitmap the bitmap to retrieve . */
public static void addFrame ( String uri , Map < String , String > headers , long time , Bitmap bitmap ) { } }

implementation: addFrame ( toDataSource ( uri , headers ) , time , bitmap ) ;


signature:
public class ShadowMediaMetadataRetriever { /** * Adds the given bitmap at the given time for the given data source .
 * Uses < tt > path < / tt > to call { @ link org . robolectric . shadows . util . DataSource # toDataSource ( FileDescriptor ) } and
 * then calls { @ link # addFrame ( DataSource , long , Bitmap ) } . This
 * method is retained mostly for backwards compatibility ;
 * you can call { @ link # addFrame ( DataSource , long , Bitmap ) } directly .
 * @ param fd file descriptor of the data source .
 * @ param time the playback time at which the specified bitmap
 * should be retrieved .
 * @ param bitmap the bitmap to retrieve . */
public static void addFrame ( FileDescriptor fd , long time , Bitmap bitmap ) { } }

implementation: addFrame ( toDataSource ( fd ) , time , bitmap ) ;


signature:
public class ShadowMediaMetadataRetriever { /** * Adds the given bitmap at the given time for the given data source .
 * Uses < tt > path < / tt > to call { @ link org . robolectric . shadows . util . DataSource # toDataSource ( FileDescriptor , long , long ) } and
 * then calls { @ link # addFrame ( DataSource , long , Bitmap ) } . This
 * method is retained mostly for backwards compatibility ;
 * you can call { @ link # addFrame ( DataSource , long , Bitmap ) } directly .
 * @ param fd file descriptor of the data source .
 * @ param offset the byte offset within the specified file from which to start reading the data .
 * @ param length the number of bytes to read from the file .
 * @ param time the playback time at which the specified bitmap
 * should be retrieved .
 * @ param bitmap the bitmap to retrieve . */
public static void addFrame ( FileDescriptor fd , long offset , long length , long time , Bitmap bitmap ) { } }

implementation: addFrame ( toDataSource ( fd , offset , length ) , time , bitmap ) ;


signature:
public class ShadowApplicationPackageManager { /** * There is no copy constructor for PackageInfo */
private static PackageInfo newPackageInfo ( PackageInfo orig ) { } }

implementation: Parcel parcel = Parcel . obtain ( ) ; orig . writeToParcel ( parcel , 0 ) ; parcel . setDataPosition ( 0 ) ; return PackageInfo . CREATOR . createFromParcel ( parcel ) ;


signature:
public class ShadowApplicationPackageManager { /** * Behaves as { @ link # queryIntentServices ( Intent , int ) } and currently ignores userId . */
@ Implementation ( minSdk = JELLY_BEAN_MR1 ) protected List < ResolveInfo > queryIntentServicesAsUser ( Intent intent , int flags , int userId ) { } }

implementation: return queryIntentServices ( intent , flags ) ;


signature:
public class ShadowApplicationPackageManager { /** * Behaves as { @ link # queryIntentActivities ( Intent , int ) } and currently ignores userId . */
@ Implementation ( minSdk = JELLY_BEAN_MR1 ) protected List < ResolveInfo > queryIntentActivitiesAsUser ( Intent intent , int flags , int userId ) { } }

implementation: return queryIntentActivities ( intent , flags ) ;


signature:
public class ShadowApplicationPackageManager { /** * Returns whether a permission should be treated as granted to the package for backward
 * compatibility reasons .
 * Before Robolectric 4.0 the ShadowPackageManager treated every requested permission as
 * automatically granted . 4.0 changes this behavior , and only treats a permission as granted if
 * PackageInfo . requestedPermissionFlags [ permissionIndex ] & REQUESTED _ PERMISSION _ GRANTED = =
 * REQUESTED _ PERMISSION _ GRANTED which matches the real PackageManager ' s behavior .
 * Since many existing tests didn ' t set the requestedPermissionFlags on their { @ code
 * PackageInfo } objects , but assumed that all permissions are granted , we auto - grant all
 * permissions if the requestedPermissionFlags is not set . If the requestedPermissionFlags is set ,
 * we assume that the test is configuring the permission grant state , and we don ' t override this
 * setting . */
private boolean isGrantedForBackwardsCompatibility ( String pkgName , PackageInfo permissionsInfo ) { } }

implementation:
// Note : it might be cleaner to auto - grant these permissions when the package is added to the
// PackageManager . But many existing tests modify the requested permissions _ after _ adding the
// package to the PackageManager , without updating the requestedPermissionsFlags .
return permissionsInfo . requestedPermissionsFlags == null // Robolectric uses the PackageParser to create the current test package ' s PackageInfo from
// the manifest XML . The parser populates the requestedPermissionsFlags , but doesn ' t grant
// the permissions . Several tests rely on the test package being granted all permissions , so
// we treat this as a special case .
|| pkgName . equals ( RuntimeEnvironment . application . getPackageName ( ) ) ;


signature:
public class ShadowApplicationPackageManager { /** * Modifies the component in place using .
 * @ throws NameNotFoundException when component is filtered out by a flag */
private void applyFlagsToComponentInfo ( ComponentInfo componentInfo , int flags ) throws NameNotFoundException { } }

implementation:
componentInfo . name = ( componentInfo . name == null ) ? "" : componentInfo . name ; ApplicationInfo applicationInfo = componentInfo . applicationInfo ; boolean isApplicationEnabled = true ; if ( applicationInfo != null ) { if ( applicationInfo . packageName == null ) { applicationInfo . packageName = componentInfo . packageName ; } applyFlagsToApplicationInfo ( componentInfo . applicationInfo , flags ) ; componentInfo . packageName = applicationInfo . packageName ; isApplicationEnabled = applicationInfo . enabled ; } if ( ( flags & GET_META_DATA ) == 0 ) { componentInfo . metaData = null ; } boolean isComponentEnabled = isComponentEnabled ( componentInfo ) ; if ( ( flags & MATCH_ALL ) != 0 && Build . VERSION . SDK_INT >= 23 ) { return ; } // Android don ' t override the enabled field of component with the actual value .
boolean isEnabledForFiltering = isComponentEnabled && ( Build . VERSION . SDK_INT >= 24 ? isApplicationEnabled : true ) ; if ( ( flags & MATCH_DISABLED_COMPONENTS ) == 0 && ! isEnabledForFiltering ) { throw new NameNotFoundException ( "Disabled component: " + componentInfo ) ; } if ( isFlagSet ( flags , PackageManager . MATCH_SYSTEM_ONLY ) ) { if ( applicationInfo == null ) { // TODO : for backwards compatibility just skip filtering . In future should just remove
// invalid resolve infos from list
} else { final int applicationFlags = applicationInfo . flags ; if ( ( applicationFlags & ApplicationInfo . FLAG_SYSTEM ) != ApplicationInfo . FLAG_SYSTEM ) { throw new NameNotFoundException ( "Not system component: " + componentInfo ) ; } } } if ( ! isFlagSet ( flags , MATCH_UNINSTALLED_PACKAGES ) && isValidComponentInfo ( componentInfo ) && hiddenPackages . contains ( componentInfo . applicationInfo . packageName ) ) { throw new NameNotFoundException ( "Uninstalled package: " + componentInfo ) ; }


signature: public class ShadowApplicationPackageManager { @ Implementation ( minSdk = N ) protected PackageInfo getPackageInfoAsUser ( String packageName , int flags , int userId ) throws NameNotFoundException { } }

implementation: return null ;


signature:
public class ShadowApplicationPackageManager { /** * Returns the index of the given permission in the PackageInfo . requestedPermissions array , or - 1
 * if it ' s not found . */
private int getPermissionIndex ( PackageInfo packageInfo , String permissionName ) { } }

implementation: if ( packageInfo . requestedPermissions != null ) { for ( int i = 0 ; i < packageInfo . requestedPermissions . length ; i ++ ) { if ( permissionName . equals ( packageInfo . requestedPermissions [ i ] ) ) { return i ; } } } return - 1 ;


signature:
public class ShadowApplicationPackageManager { /** * Behaves as { @ link # resolveActivity ( Intent , int ) } and currently ignores userId . */
@ Implementation ( minSdk = JELLY_BEAN_MR1 ) protected ResolveInfo resolveActivityAsUser ( Intent intent , int flags , int userId ) { } }

implementation: return resolveActivity ( intent , flags ) ;


signature:
public class ShadowApplicationPackageManager { /** * Gets the unbadged icon based on the values set by { @ link
 * ShadowPackageManager # setUnbadgedApplicationIcon } or returns null if nothing has been set . */
@ Implementation ( minSdk = LOLLIPOP_MR1 ) protected Drawable loadUnbadgedItemIcon ( PackageItemInfo itemInfo , ApplicationInfo appInfo ) { } }

implementation: Drawable result = unbadgedApplicationIcons . get ( itemInfo . packageName ) ; if ( result != null ) { return result ; } return Shadow . directlyOn ( realObject , ApplicationPackageManager . class ) . loadUnbadgedItemIcon ( itemInfo , appInfo ) ;


signature:
public class ShadowApplicationPackageManager { /** * Adds a profile badge to the icon .
 * This implementation just returns the unbadged icon , as some default implementations add an
 * internal resource to the icon that is unavailable to Robolectric . */
@ Implementation ( minSdk = LOLLIPOP ) protected Drawable getUserBadgedIcon ( Drawable icon , UserHandle user ) { } }

implementation: return icon ;


signature:
public class ShadowApplicationPackageManager { /** * Returns whether the current user profile has a profile owner or a device owner . */
private boolean hasProfileOwnerOrDeviceOwnerOnCurrentUser ( ) { } }

implementation: DevicePolicyManager devicePolicyManager = ( DevicePolicyManager ) context . getSystemService ( Context . DEVICE_POLICY_SERVICE ) ; return devicePolicyManager . getProfileOwner ( ) != null || ( UserHandle . of ( UserHandle . myUserId ( ) ) . isSystem ( ) && devicePolicyManager . getDeviceOwner ( ) != null ) ;


signature:
public class StringResources { /** * Provides escaping of String resources as described
 * [ here ] ( http : / / developer . android . com / guide / topics / resources / string - resource . html # FormattingAndStyling ) .
 * @ param text Text to escape .
 * @ return Escaped text . */
@ VisibleForTesting static String escape ( String text ) { } }

implementation:
// unwrap double quotes
if ( text . length ( ) > 1 && text . charAt ( 0 ) == '"' && text . charAt ( text . length ( ) - 1 ) == '"' ) { text = text . substring ( 1 , text . length ( ) - 1 ) ; } int i = 0 ; int length = text . length ( ) ; StringBuilder result = new StringBuilder ( text . length ( ) ) ; while ( true ) { int j = text . indexOf ( '\\' , i ) ; if ( j == - 1 ) { result . append ( removeUnescapedDoubleQuotes ( text . substring ( i ) ) ) ; break ; } result . append ( removeUnescapedDoubleQuotes ( text . substring ( i , j ) ) ) ; if ( j == length - 1 ) { // dangling backslash
break ; } boolean isUnicodeEscape = false ; char escapeCode = text . charAt ( j + 1 ) ; switch ( escapeCode ) { case '\'' : case '"' : case '\\' : case '?' : case '@' : case '#' : result . append ( escapeCode ) ; break ; case 'n' : result . append ( '\n' ) ; break ; case 't' : result . append ( '\t' ) ; break ; case 'u' : isUnicodeEscape = true ; break ; default : Logger . strict ( "Unsupported string resource escape code '%s'" , escapeCode ) ; } if ( ! isUnicodeEscape ) { i = j + 2 ; } else { j += 2 ; if ( length - j < CODE_POINT_LENGTH ) { throw new IllegalArgumentException ( "Too short code point: \\u" + text . substring ( j ) ) ; } String codePoint = text . substring ( j , j + CODE_POINT_LENGTH ) ; result . append ( extractCodePoint ( codePoint ) ) ; i = j + CODE_POINT_LENGTH ; } } return result . toString ( ) ;


signature:
public class StringResources { /** * Converts code points in a given string to actual characters . This method doesn ' t handle code
 * points whose char counts are 2 . In other words , this method doesn ' t handle U + 10XXXX . */
private static char [ ] extractCodePoint ( String codePoint ) { } }

implementation:
try { return Character . toChars ( Integer . valueOf ( codePoint , 16 ) ) ; } catch ( IllegalArgumentException e ) { // This may be caused by NumberFormatException of Integer . valueOf ( ) or
// IllegalArgumentException of Character . toChars ( ) .
throw new IllegalArgumentException ( "Invalid code point: \\u" + codePoint , e ) ; }


signature:
public class Reflector { /** * Returns an object which provides accessors for invoking otherwise inaccessible methods and
 * fields .
 * @ param iClass an interface with methods matching private methods on the target
 * @ param target the target object */
public static < T > T reflector ( Class < T > iClass , Object target ) { } }

implementation: Class < ? > targetClass = determineTargetClass ( iClass ) ; Constructor < ? extends T > ctor = ( Constructor < ? extends T > ) CACHE . get ( iClass ) ; try { if ( ctor == null ) { Class < ? extends T > reflectorClass = createReflectorClass ( iClass , targetClass ) ; ctor = reflectorClass . getConstructor ( targetClass ) ; ctor . setAccessible ( true ) ; } CACHE . put ( iClass , ctor ) ; return ctor . newInstance ( target ) ; } catch ( NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e ) { throw new IllegalStateException ( e ) ; }


signature:
public class ShadowSensorManager { /** * Creates a { @ link SensorEvent } with the given value array size , which the caller should set
 * based on the type of { @ link Sensor } which is being emulated .
 * < p > Callers can then specify individual values for the event . For example , for a proximity event
 * a caller may wish to specify the distance value :
 * < pre > { @ code
 * event . values [ 0 ] = distance ;
 * } < / pre >
 * < p > See { @ link SensorEvent # values } for more information about values . */
public static SensorEvent createSensorEvent ( int valueArraySize ) { } }

implementation: checkArgument ( valueArraySize > 0 ) ; ClassParameter < Integer > valueArraySizeParam = new ClassParameter < > ( int . class , valueArraySize ) ; return ReflectionHelpers . callConstructor ( SensorEvent . class , valueArraySizeParam ) ;


signature:
public class ShadowContentResolver { /** * If a { @ link ContentProvider } is registered for the given { @ link Uri } , its { @ link
 * ContentProvider # insert ( Uri , ContentValues ) } method will be invoked .
 * < p > Tests can verify that this method was called using { @ link # getStatements ( ) } or { @ link
 * # getInsertStatements ( ) } .
 * < p > If no appropriate { @ link ContentProvider } is found , no action will be taken and a { @ link
 * Uri } including the incremented value set with { @ link # setNextDatabaseIdForInserts ( int ) } will
 * returned . */
@ Implementation protected final Uri insert ( Uri url , ContentValues values ) { } }

implementation: ContentProvider provider = getProvider ( url ) ; ContentValues valuesCopy = ( values == null ) ? null : new ContentValues ( values ) ; InsertStatement insertStatement = new InsertStatement ( url , provider , valuesCopy ) ; statements . add ( insertStatement ) ; insertStatements . add ( insertStatement ) ; if ( provider != null ) { return provider . insert ( url , values ) ; } else { return Uri . parse ( url . toString ( ) + "/" + ++ nextDatabaseIdForInserts ) ; }


signature:
public class ShadowContentResolver { /** * If a { @ link ContentProvider } is registered for the given { @ link Uri } , its
 * { @ link ContentProvider # update ( Uri , ContentValues , String , String [ ] ) } method will be invoked .
 * Tests can verify that this method was called using { @ link # getStatements ( ) } or
 * { @ link # getUpdateStatements ( ) } .
 * @ return If no appropriate { @ link ContentProvider } is found , no action will be taken and 1 will
 * be returned . */
@ Implementation protected int update ( Uri uri , ContentValues values , String where , String [ ] selectionArgs ) { } }

implementation: ContentProvider provider = getProvider ( uri ) ; ContentValues valuesCopy = ( values == null ) ? null : new ContentValues ( values ) ; UpdateStatement updateStatement = new UpdateStatement ( uri , provider , valuesCopy , where , selectionArgs ) ; statements . add ( updateStatement ) ; updateStatements . add ( updateStatement ) ; if ( provider != null ) { return provider . update ( uri , values , where , selectionArgs ) ; } else { return 1 ; }


signature:
public class ShadowContentResolver { /** * If a { @ link ContentProvider } is registered for the given { @ link Uri } , its { @ link
 * ContentProvider # delete ( Uri , String , String [ ] ) } method will be invoked .
 * < p > Tests can verify that this method was called using { @ link # getDeleteStatements ( ) } or { @ link
 * # getDeletedUris ( ) } .
 * < p > If no appropriate { @ link ContentProvider } is found , no action will be taken and { @ code 1}
 * will be returned . */
@ Implementation protected final int delete ( Uri url , String where , String [ ] selectionArgs ) { } }

implementation: ContentProvider provider = getProvider ( url ) ; DeleteStatement deleteStatement = new DeleteStatement ( url , provider , where , selectionArgs ) ; statements . add ( deleteStatement ) ; deleteStatements . add ( deleteStatement ) ; if ( provider != null ) { return provider . delete ( url , where , selectionArgs ) ; } else { return 1 ; }


signature:
public class ShadowContentResolver { /** * If a { @ link ContentProvider } is registered for the given { @ link Uri } , its { @ link
 * ContentProvider # bulkInsert ( Uri , ContentValues [ ] ) } method will be invoked .
 * < p > Tests can verify that this method was called using { @ link # getStatements ( ) } or { @ link
 * # getInsertStatements ( ) } .
 * < p > If no appropriate { @ link ContentProvider } is found , no action will be taken and the number
 * of rows in { @ code values } will be returned . */
@ Implementation protected final int bulkInsert ( Uri url , ContentValues [ ] values ) { } }

implementation: ContentProvider provider = getProvider ( url ) ; InsertStatement insertStatement = new InsertStatement ( url , provider , values ) ; statements . add ( insertStatement ) ; insertStatements . add ( insertStatement ) ; if ( provider != null ) { return provider . bulkInsert ( url , values ) ; } else { return values . length ; }


signature:
public class ShadowContentResolver { /** * Retrieve information on the status of the given account .
 * @ param account the account
 * @ param authority the authority
 * @ param create whether to create if no such account is found
 * @ return the account ' s status */
public static Status getStatus ( Account account , String authority , boolean create ) { } }

implementation: Map < Account , Status > map = syncableAccounts . get ( authority ) ; if ( map == null ) { map = new HashMap < > ( ) ; syncableAccounts . put ( authority , map ) ; } Status status = map . get ( account ) ; if ( status == null && create ) { status = new Status ( ) ; map . put ( account , status ) ; } return status ;


signature:
public class ShadowContentResolver { /** * Returns the content observers registered for updates under the given URI .
 * Will be empty if no observer is registered .
 * @ param uri Given URI
 * @ return The content observers , or null */
public Collection < ContentObserver > getContentObservers ( Uri uri ) { } }

implementation: ArrayList < ContentObserver > observers = new ArrayList < > ( 1 ) ; for ( ContentObserverEntry entry : contentObservers ) { if ( entry . matches ( uri ) ) { observers . add ( entry . observer ) ; } } return observers ;


signature:
public class ShadowDisplayManager { /** * Adds a simulated display and drain the main looper queue to ensure all the callbacks are
 * processed .
 * @ param qualifiersStr the { @ link Qualifiers } string representing characteristics of the new
 * display .
 * @ return the new display ' s ID */
public static int addDisplay ( String qualifiersStr ) { } }

implementation: int id = getShadowDisplayManagerGlobal ( ) . addDisplay ( createDisplayInfo ( qualifiersStr , null ) ) ; shadowMainLooper ( ) . idle ( ) ; return id ;


signature:
public class ShadowDisplayManager { /** * internal only */
public static void configureDefaultDisplay ( Configuration configuration , DisplayMetrics displayMetrics ) { } }

implementation: ShadowDisplayManagerGlobal shadowDisplayManagerGlobal = getShadowDisplayManagerGlobal ( ) ; if ( DisplayManagerGlobal . getInstance ( ) . getDisplayIds ( ) . length != 0 ) { throw new IllegalStateException ( "this method should only be called by Robolectric" ) ; } shadowDisplayManagerGlobal . addDisplay ( createDisplayInfo ( configuration , displayMetrics ) ) ;


signature:
public class ShadowDisplayManager { /** * Changes properties of a simulated display . If ` qualifiersStr ` starts with a plus ( ` + ` ) sign ,
 * the display ' s previous configuration is modified with the given qualifiers ; otherwise defaults
 * are applied as described [ here ] ( http : / / robolectric . org / device - configuration / ) .
 * < p > Idles the main looper to ensure all listeners are notified .
 * @ param displayId the display id to change
 * @ param qualifiersStr the { @ link Qualifiers } string representing characteristics of the new
 * display */
public static void changeDisplay ( int displayId , String qualifiersStr ) { } }

implementation: DisplayInfo baseDisplayInfo = DisplayManagerGlobal . getInstance ( ) . getDisplayInfo ( displayId ) ; DisplayInfo displayInfo = createDisplayInfo ( qualifiersStr , baseDisplayInfo ) ; getShadowDisplayManagerGlobal ( ) . changeDisplay ( displayId , displayInfo ) ; shadowMainLooper ( ) . idle ( ) ;


signature:
public class ShadowDisplayManager { /** * Changes properties of a simulated display . The original properties will be passed to the
 * ` consumer ` , which may modify them in place . The display will be updated with the new
 * properties .
 * @ param displayId the display id to change
 * @ param consumer a function which modifies the display properties */
static void changeDisplay ( int displayId , Consumer < DisplayConfig > consumer ) { } }

implementation: DisplayInfo displayInfo = DisplayManagerGlobal . getInstance ( ) . getDisplayInfo ( displayId ) ; if ( displayInfo != null ) { DisplayConfig displayConfig = new DisplayConfig ( displayInfo ) ; consumer . accept ( displayConfig ) ; displayConfig . copyTo ( displayInfo ) ; fixNominalDimens ( displayInfo ) ; } getShadowDisplayManagerGlobal ( ) . changeDisplay ( displayId , displayInfo ) ;


signature:
public class ShadowDisplayManager { /** * Returns the current display saturation level set via { @ link
 * android . hardware . display . DisplayManager # setSaturationLevel ( float ) } . */
public float getSaturationLevel ( ) { } }

implementation: if ( RuntimeEnvironment . getApiLevel ( ) >= Build . VERSION_CODES . Q ) { ShadowColorDisplayManager shadowCdm = extract ( context . getSystemService ( Context . COLOR_DISPLAY_SERVICE ) ) ; return shadowCdm . getSaturationLevel ( ) / 100f ; } return getShadowDisplayManagerGlobal ( ) . getSaturationLevel ( ) ;


signature:
public class ShadowTextView { /** * Returns the text string of this { @ code TextView } .
 * Robolectric extension . */
@ Override public String innerText ( ) { } }

implementation: CharSequence text = realTextView . getText ( ) ; return ( text == null || realTextView . getVisibility ( ) != View . VISIBLE ) ? "" : text . toString ( ) ;


signature:
public class ShadowDebug { /** * Forked from android . os . Debug */
private static String fixTracePath ( String tracePath ) { } }

implementation: String defaultTraceBody = "dmtrace" ; String defaultTraceExtension = ".trace" ; if ( tracePath == null || tracePath . charAt ( 0 ) != '/' ) { final File dir = RuntimeEnvironment . application . getExternalFilesDir ( null ) ; if ( tracePath == null ) { tracePath = new File ( dir , defaultTraceBody ) . getAbsolutePath ( ) ; } else { tracePath = new File ( dir , tracePath ) . getAbsolutePath ( ) ; } } if ( ! tracePath . endsWith ( defaultTraceExtension ) ) { tracePath += defaultTraceExtension ; } return tracePath ;


signature:
public class Code { /** * 统计某个文件的信息 。
 * @ param file
 * 被分析的文件
 * @ param conf
 * 代码分析配置项 ( 为空的话 , 则按照JAVA代码来进行分析统计 )
 * @ return 分析结果 */
public static CodeAnalysisResult countingCode ( File file , CodeAnalysisConf conf ) { } }

implementation:
if ( ! Files . isFile ( file ) ) { throw new RuntimeException ( "file is not a File, can't analysis it." ) ; } if ( null == conf ) { conf = CODE_INFO_JAVA ; } BufferedReader br ; try { br = new BufferedReader ( new FileReader ( file ) ) ; } catch ( FileNotFoundException e ) { throw Lang . wrapThrow ( e ) ; } boolean comment = false ; long whiteLines = 0 ; long commentLines = 0 ; long normalLines = 0 ; long importLines = 0 ; String line = "" ; try { while ( ( line = br . readLine ( ) ) != null ) { line = line . trim ( ) ; if ( line . startsWith ( conf . multiLineCommentStart ) && ! line . endsWith ( conf . multiLineCommentEnd ) ) { // 多行注释开始
commentLines ++ ; comment = true ; } else if ( true == comment ) { // 多行注释结束
commentLines ++ ; if ( line . endsWith ( conf . multiLineCommentEnd ) ) { comment = false ; } } else if ( Regex . match ( conf . emptyLinePattern , line ) ) { // 空白行 ( 多行注解内的空白行不算在内 )
whiteLines ++ ; } else if ( line . startsWith ( conf . singleLineCommentStart ) || ( line . startsWith ( conf . multiLineCommentStart ) && line . endsWith ( conf . multiLineCommentEnd ) ) ) { // 单行注释
commentLines ++ ; } else if ( line . startsWith ( conf . pakStart ) || line . startsWith ( conf . impStart ) ) { // package与import
importLines ++ ; } else { // 代码行
normalLines ++ ; } } } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; } if ( br != null ) { try { br . close ( ) ; } catch ( IOException e ) { throw Lang . wrapThrow ( e ) ; } } // 记录并返回统计结果
return new CodeAnalysisResult ( normalLines , commentLines , whiteLines , importLines ) ;


signature:
public class Code { /** * 统计某个目录下 , 以特定后缀名结尾的源码信息 。
 * @ param src
 * 源代码目录
 * @ param suffix
 * 文件后缀 ( 为空的话 , 则统计所有类型文件 )
 * @ param countSubFolder
 * 是否统计子文件夹 ( true的话 , 将递归统计所有子文件夹 )
 * @ param conf
 * 代码分析配置项 ( 为空的话 , 则按照JAVA代码来进行分析统计 ) */
public static CodeStatisticsResult countingCode ( File src , String suffix , boolean countSubFolder , CodeAnalysisConf conf ) { } }

implementation: if ( ! Files . isDirectory ( src ) ) { throw new RuntimeException ( "src is not a File, can't analysis it." ) ; } if ( null == conf ) { conf = CODE_INFO_JAVA ; } CodeStatisticsResult statisticsResult = new CodeStatisticsResult ( src ) ; boolean useParticularType = ! Strings . isBlank ( suffix ) ; folderAnalysis ( src , useParticularType , suffix , countSubFolder , conf , statisticsResult ) ; return statisticsResult ;


signature:
public class Tasks { /** * 通过 cron 表达式来配置任务的启动时间
 * @ param task
 * @ param cronExpression */
public static void scheduleAtCron ( final Runnable task , String cronExpression ) { } }

implementation: TimeSchedule timeSchedule = new TimeSchedule ( task , cronExpression ) ; timeSchedule . start ( ) ;


signature:
public class Tasks { /** * 立即启动 , 并以固定的频率来运行任务 。 后续任务的启动时间不受前次任务延时影响 。
 * @ param task 具体待执行的任务
 * @ param periodSeconds 每次执行任务的间隔时间 ( 单位秒 ) */
public static ScheduledFuture < ? > scheduleAtFixedRate ( Runnable task , long periodSeconds ) { } }

implementation: return scheduleAtFixedRate ( task , 0 , periodSeconds , TimeUnit . SECONDS ) ;


signature:
public class Tasks { /** * 在指定的延时之后开始以固定的频率来运行任务 。 后续任务的启动时间不受前次任务延时影响 。
 * @ param task 具体待执行的任务
 * @ param initialDelay 首次执行任务的延时时间
 * @ param periodSeconds 每次执行任务的间隔时间 ( 单位秒 )
 * @ param unit 时间单位 */
public static ScheduledFuture < ? > scheduleAtFixedRate ( Runnable task , long initialDelay , long periodSeconds , TimeUnit unit ) { } }

implementation: return taskScheduler . scheduleAtFixedRate ( task , initialDelay , periodSeconds , unit ) ;


signature:
public class Tasks { /** * 立即启动 , 两次任务间保持固定的时间间隔
 * @ param task 具体待执行的任务
 * @ param periodSeconds 两次任务的间隔时间 ( 单位秒 ) */
public static ScheduledFuture < ? > scheduleWithFixedDelay ( Runnable task , long periodSeconds ) { } }

implementation: return scheduleWithFixedDelay ( task , 0 , periodSeconds , TimeUnit . SECONDS ) ;


signature:
public class Tasks { /** * 在指定的延时之后启动 , 两次任务间保持固定的时间间隔
 * @ param task 具体待执行的任务
 * @ param initialDelay 首次执行任务的延时时间
 * @ param period 两次任务的间隔时间 ( 单位秒 )
 * @ param unit 时间单位 */
public static ScheduledFuture < ? > scheduleWithFixedDelay ( Runnable task , long initialDelay , long period , TimeUnit unit ) { } }

implementation: return taskScheduler . scheduleWithFixedDelay ( task , initialDelay , period , unit ) ;


signature:
public class Tasks { /** * 在指定的时间点启动 , 两次任务间保持固定的时间间隔
 * @ param task 具体待执行的任务
 * @ param startTime 首次运行的时间点 , 支持 " yyyy - MM - dd HH : mm : ss " 格式
 * @ param period 两次任务的间隔时间
 * @ param unit 时间单位 */
public static void scheduleWithFixedDelay ( Runnable task , String startTime , long period , TimeUnit unit ) throws ParseException { } }

implementation: Date dt = Times . D ( startTime ) ; scheduleWithFixedDelay ( task , dt , period , unit ) ;


signature:
public class Tasks { /** * 在指定的时间点启动 , 两次任务间保持固定的时间间隔
 * @ param task 具体待执行的任务
 * @ param startTime 首次运行的时间点
 * @ param period 两次任务的间隔时间
 * @ param unit 时间单位 */
public static void scheduleWithFixedDelay ( final Runnable task , Date startTime , final long period , final TimeUnit unit ) { } }

implementation: final Timer timer = new Timer ( ) ; timer . schedule ( new TimerTask ( ) { @ Override public void run ( ) { taskScheduler . scheduleWithFixedDelay ( task , 0 , period , unit ) ; timer . cancel ( ) ; timerList . remove ( timer ) ; } } , startTime ) ; timerList . add ( timer ) ;


signature:
public class Tasks { /** * 在指定的时间点启动任务只运行一次
 * @ param task 具体待执行的任务
 * @ param startTime 运行的时间点 */
public static void scheduleAtFixedTime ( final Runnable task , Date startTime ) { } }

implementation: final Timer timer = new Timer ( ) ; timer . schedule ( new TimerTask ( ) { @ Override public void run ( ) { taskScheduler . execute ( task ) ; timer . cancel ( ) ; timerList . remove ( timer ) ; } } , startTime ) ; timerList . add ( timer ) ;


signature:
public class Tasks { /** * 关闭定时任务服务
 * < p > 系统关闭时可调用此方法终止正在执行的定时任务 , 一旦关闭后不允许再向线程池中添加任务 , 否则会报RejectedExecutionException异常 < / p > */
public static void depose ( ) { } }

implementation:
int timerNum = timerList . size ( ) ; // 清除Timer
synchronized ( timerList ) { for ( Timer t : timerList ) t . cancel ( ) ; timerList . clear ( ) ; } List < Runnable > awaitingExecution = taskScheduler . shutdownNow ( ) ; logger . infof ( "Tasks stopping. Tasks awaiting execution: %d" , timerNum + awaitingExecution . size ( ) ) ;


signature:
public class R { /** * 将一个 UU64 表示的紧凑字符串 , 变成 UU16 表示的字符串
 * < pre >
 * 每次取2个字符 , 恢复成3个byte , 重复10次 , 最后一次 , 是用最后2个字符 , 恢复回2个byte < / prev >
 * @ param uu64
 * uu64 64进制表示的 UUID , 内容为 [ \ \ - 0-9a - zA - Z _ ]
 * @ return 16进制表示的紧凑格式的 UUID */
public static String UU16FromUU64 ( String uu64 ) { } }

implementation:
byte [ ] bytes = new byte [ 32 ] ; char [ ] cs = uu64 . toCharArray ( ) ; int index = 0 ; // 每次取2个字符 , 恢复成3个byte , 重复10次 ,
for ( int i = 0 ; i < 10 ; i ++ ) { int off = i * 2 ; char cl = cs [ off ] ; char cr = cs [ off + 1 ] ; int l = Arrays . binarySearch ( _UU64 , cl ) ; int r = Arrays . binarySearch ( _UU64 , cr ) ; int n = ( l << 6 ) | r ; bytes [ index ++ ] = ( byte ) ( ( n & 0xF00 ) >>> 8 ) ; bytes [ index ++ ] = ( byte ) ( ( n & 0xF0 ) >>> 4 ) ; bytes [ index ++ ] = ( byte ) ( n & 0xF ) ; } // 最后一次 , 是用最后2个字符 , 恢复回2个byte
char cl = cs [ 20 ] ; char cr = cs [ 21 ] ; int l = Arrays . binarySearch ( _UU64 , cl ) ; int r = Arrays . binarySearch ( _UU64 , cr ) ; int n = ( l << 2 ) | r ; bytes [ index ++ ] = ( byte ) ( ( n & 0xF0 ) >>> 4 ) ; bytes [ index ++ ] = ( byte ) ( n & 0xF ) ; // 返回 UUID 对象
char [ ] names = new char [ 32 ] ; for ( int i = 0 ; i < bytes . length ; i ++ ) names [ i ] = _UU16 [ bytes [ i ] ] ; return new String ( names ) ;


signature:
public class Cnd { /** * 用字符串和参数格式化出一个条件语句 , 注意 , 不会抹除特殊字符
 * @ param format sql条件
 * @ param args 参数
 * @ return 条件对象 */
public static Condition format ( String format , Object ... args ) { } }

implementation: return Strings . isBlank ( format ) ? null : new SimpleCondition ( format , args ) ;


signature:
public class Cnd { /** * 直接用字符串生成一个条件对象
 * @ param str sql条件
 * @ return 条件对象 */
public static Condition wrap ( String str ) { } }

implementation: return Strings . isBlank ( str ) ? null : new SimpleCondition ( ( Object ) str ) ;


signature:
public class Cnd { /** * 使用CharSegment拼装一个条件对象
 * @ param sql sql模板
 * @ param value 参数
 * @ return 条件对象
 * @ see org . nutz . lang . segment . CharSegment */
public static Condition wrap ( String sql , Object value ) { } }

implementation: return Strings . isBlank ( sql ) ? null : new SimpleCondition ( new CharSegment ( sql ) . setBy ( value ) ) ;


signature:
public class Cnd { /** * 生成一个条件表达式
 * @ param name Java属性或字段名称
 * @ param op 操作符 , 可以是 = like 等等
 * @ param value 参数值 .
 * @ return 条件表达式 */
public static SqlExpression exp ( String name , String op , Object value ) { } }

implementation: if ( value != null && value instanceof Nesting ) { return NestExps . create ( name , op , ( Nesting ) value ) ; } return Exps . create ( name , op , value ) ;


signature:
public class Cnd { /** * 生成一个条件表达式组
 * @ param name Java属性或字段名称
 * @ param op 操作符 , 可以是 = like 等等
 * @ param value 参数值 .
 * @ return 条件表达式组 */
public static SqlExpressionGroup exps ( String name , String op , Object value ) { } }

implementation: return exps ( exp ( name , op , value ) ) ;


signature:
public class Cnd { /** * 生成一个新的Cnd实例
 * @ param name java属性或字段名称 , 推荐用Java属性
 * @ param op 操作符 , 可以是 = like等等
 * @ param value 参数值 . 如果操作符是between , 参数值需要是new Object [ ] { 12,39 } 形式
 * @ return Cnd实例 */
public static Cnd where ( String name , String op , Object value ) { } }

implementation: return new Cnd ( Cnd . exp ( name , op , value ) ) ;


signature:
public class Cnd { /** * 当dir为asc时判断为升序 , 否则判定为降序 . cnd . orderBy ( " age " , " asc " )
 * @ param name Java属性 / 字段属性
 * @ param dir asc或其他
 * @ return OrderBy实例 , 事实上就是当前对象 */
public OrderBy orderBy ( String name , String dir ) { } }

implementation: if ( "asc" . equalsIgnoreCase ( dir ) ) { this . asc ( name ) ; } else { this . desc ( name ) ; } return this ;


signature:
public class Cnd { /** * Cnd . where ( . . . ) . and ( " age " , " < " , 40)
 * @ param name Java属性或字段名称 , 推荐用Java属性 , 如果有的话
 * @ param op 操作符 , 可以是 = like等
 * @ param value 参数值 , 如果是between的话需要传入new Object [ ] { 19,28}
 * @ return 当前对象 , 用于链式调用 */
public Cnd and ( String name , String op , Object value ) { } }

implementation: return and ( Cnd . exp ( name , op , value ) ) ;