We can use this function to see that the conversion is not made during parsing:
parseString[s_String, prep : (True | False) : True] :=
FrontEndExecute[FrontEnd`UndocumentedTestFEParserPacket[s, prep]]
parseString["x x"]
{BoxData[RowBox[{"x", "x"}]], StandardForm}
We can use this to see that the conversion does not take place while converting boxes to StandardForm:
ToExpression[RowBox[{"x", "x"}], StandardForm, HoldComplete] // FullForm
HoldComplete[Times[x,x]]
We can see that the rule is applied as part of the normal evaluation sequence:
Times[x, x] // TracePrint
x x
Times
x
x
(x^2)
Power
x
2
You cannot generally "stop this conversion" but you can temporarily disable the rules for Times using Block:
Block[{Times},
ToString[x x]
]
"Times[x, x]"
You can also Hold or HoldComplete expressions and apply your own rules.
Neither of these methods lets Times otherwise behave as desired. I have lamented this problem myself with regard to Subtract and Divide as the "equivalent" forms they are converted into are neither equivalent nor as fast.