code: @VisibleForTesting
    synchronized boolean canAllocate(int sizeInBytes) {
      int hardCap = mPoolParams.maxSizeHardCap;
  
      // even with our best effort we cannot ensure hard cap limit.
      // Return immediately - no point in trimming any space
      if (sizeInBytes > hardCap - mUsed.mNumBytes) {
        mPoolStatsTracker.onHardCapReached();
        return false;
      }
  
      // trim if we need to
      int softCap = mPoolParams.maxSizeSoftCap;
      if (sizeInBytes > softCap - (mUsed.mNumBytes + mFree.mNumBytes)) {
        trimToSize(softCap - sizeInBytes);
      }
  
      // check again to see if we're below the hard cap
      if (sizeInBytes > hardCap - (mUsed.mNumBytes + mFree.mNumBytes)) {
        mPoolStatsTracker.onHardCapReached();
        return false;
      }
  
      return true;
    }
docs: Can we allocate a value of size 'sizeInBytes' without exceeding the hard cap on the pool size?
  If allocating this value will take the pool over the hard cap, we will first trim the pool down
  to its soft cap, and then check again.
  If the current used bytes + this new value will take us above the hard cap, then we return
  false immediately - there is no point freeing up anything.
  @param sizeInBytes the size (in bytes) of the value to allocate
  @return true, if we can allocate this; false otherwise