p(String prefix, String s) takes 1 character out of s and adds it to prefix and recursively continues until s is empty.
The s.charAt(i), s.substring(0, i) + s.substring(i+1, n) part extracts a character from s.
Assume s = "Magic!" and i = 3 then charAt(i) = 'i', s.substring(0, i) = "Mag" and s.substring(i+1, n) = c!". That spilts Magic! into i and Magc!. Next time in the loop with i = 4 it will result in c + Magi!. Since it does that for every character in s every character will be in the front in one of the recursive steps.
The call hierarchy would look like this
/ p("ab", "c") - "abc"
/- p("a", "bc") x
/ \ p("ac", "b") - "acb"
/
/ / p("ba", "c") - "bac"
p("", "abc") x ---- p("b", "ac") x
\ \ p("bc", "a") - "bca"
\
\ / p("ca", "b") - "cab"
\- p("c", "ab") x
\ p("cb", "a") - "cba"
^-- 1st for loop ^- 2nd for ^- 3rd one prints