Find all words in a dictionary that can be made with a string of characters (Recursion/Binary Search)
Favor interfaces over implementations


private ArrayList&lt;String&gt; dict = new ArrayList&lt;&gt;();



This would more commonly be written as 

private List&lt;String&gt; dict = new ArrayList&lt;&gt;();


Using the interface is more flexible and easier to change.  

Dictionary types

That said, the more common type for a dictionary is 

private Set&lt;String&gt; dictionary = new HashSet&lt;&gt;();


Then you can generate all the words and check them.  

If you are committed to a binary search, consider using a NavigableSet.  

private NavigableSet&lt;String&gt; dictionary = new TreeSet&lt;&gt;();


This would give you code like 

    for (char letter : letterPool.toCharArray()) {
        String current = word + letter;

        String bound = word + (letter + 1);
        NavigableSet&lt;String&gt; prefixed = dictionary.subSet(current, true, bound, false);

        if (prefixed.isEmpty()) {
            // no need to keep looking if we didn't find anything
            continue;
        }

        // current will be the first element of the Set if present
        if (prefixed.first.equals(current)) {
            possibleWords.add(current);
            prefixed.pollFirst();
        }

        // if there's more than one letter left in the pool
        if (letterPool.size &gt; 1) {
            // recurse with it out of the pool
            String remaining = letterPool.substring(0, i) + letterPool.substring(i + 1);
            getAllValidWords(remaining, current, prefixed);
        }
    }


I changed the names of currWord to word, newLetterPool to remaining, and curr to current, as I find that easier to read.  Your mileage may vary.  

We don't need to check if letterPool or word are empty.  The code works for those cases.  

I added prefixed to the recursive call.  The reason is that we don't need to search the whole tree.  We only need the subtree.  

I moved generation of newLetterPool to the point where I know it will be used.  Prior to that we may never use it, so why waste time generating it?  

Trie

This is the application for which a Trie is designed.  That said, my experience is that they tend to be slow and memory intensive.  It takes too long to build the structure to get the gains from fast prefix searches.  

You might well find the brute force solution with a HashSet to be faster.  In that solution, you basically generate each possible permutation and then filter out just the ones that are words.  The downside is that you may check a lot of words like zxqjv.  

A Trie works best in situations where it's prebuilt and easy to load into memory or where it stays as it is for long periods of time.  Also, you should not be memory constrained.  

If you do attempt to use a Trie, consider using it only for the first few letters.  Then you can go back to something more like this.