Virat Kohli (76 batting) and Abhinav Mukund (81) put on 133 runs for the third wicket as India reached 189 for three in 46.3 overs at stumps on a rain-affected day three.
Overall, the visitors have a lead of 498 runs after they decided against enforcing the follow-on.
In reply to India's mammoth first-innings total of 600, Sri Lanka were bowled out for 291 in 78.3 overs.
After a rain-break that cost 86 minutes, playing time was extended until 6pm local time to make up for the lost overs.
More From This Section
Mukund scored only his second Test half-century off 78 balls, after his previous effort of 62 runs against the West Indies at Roseau in Dominica back in 2011.
He then proceeded to overtake that mark to record his highest score in Test cricket. Overall, he faced 116 balls, and hit eight fours.
"I have the opportunity to do something in this Test. I don't want to think ahead to the next Test. Being the first- choice opener or second-choice opener doesn't make a difference. When you get a chance in the middle, I want to capitalise on it. That's what I thought," said Mukund.
At the other end, Kohli overcame his bad patch in Tests by scoring his 15th fifty off 68 balls. This was the first time since February that the Indian skipper had crossed the 40-mark, after scoring 204 and 38 against Bangladesh at Hyderabad. His highest against Australia in five innings across three Tests was 15.
The day's play ended when Mukund fell lbw to part-timer Danushka Gunathilaka (1-15). The batsman opted to review, but that decision too went against him.
Earlier, India had reached 56 for two in 16.5 overs in the second innings when rain intervened in the second session of play. Post lunch, Ravindra Jadeja (3-67) brought the hosts' innings to a quick end as he bowled Lahiru Kumara (2).
Shikhar Dhawan (14) then fell quickly, caught at backward point off Perera (1-20), chasing a wide delivery. He put on 19 runs for the opening wicket with Mukund. He then added 37 runs with Cheteshwar Pujara (15) for the second wicket.
Some 40 minutes before tea, a thunderstorm lashed the sea-facing ground. But Lahiru Kumara (1-53) had enough time to bowl one more delivery and Pujara was caught at leg slip. An early tea was taken to make up for lost time.
Starting from overnight 154 for five, Perera and Mathews continued from where they had left yesterday evening and extended their defiant partnership. Umesh Yadav (1-78) and Jadeja got proceedings underway for India, but neither were troubled the duo as they brought up their 50-partnership off 96 balls.
Sri Lanka's 200 came up in the 57th over, and they nearly batted out the first hour without any loss when Mathews chipped a catch off Jadeja straight to Virat Kohli at short cover in the 59th over. There was slight turn available for the spinners on this day three pitch and this wicket was a result of constant pressure built up by the left-arm spinner.
Two overs later, Perera survived a confident lbw shout off Jadeja via DRS. Originally, he was ruled out lbw but the review came out in his favour, surprisingly. The ball appeared to be sailing well over the stumps, unexpectedly though as seen from Kohli's astonished reaction.
Perera then reached his fifth Test half-century off 94 balls, inclusive of four fours and three sixes. He added 36 runs with Herath for the seventh wicket and another 39 runs with Nuwan Pradeep (10) for the 8th wicket.
At the other end though, stand-in skipper Rangana Herath (9) was not so lucky as he went for a reverse sweep off Jadeja and only ended up lobbing up the ball off his glove to Ajinkya Rahane at slip for a catch. The batsman went in for DRS confidently assuming the ball had hit his arm, but Ultra-Edge replay showed that there was some glove involved.