Skip to main content
Google PlayAndroidApp Permissions

Google Play reads your manifest, not your code path

Google Play's restricted-permission rules are written against what an app declares, not against what it calls. An app that never invokes an API can still carry the permission line in its merged manifest, because a library put it there. That is a store problem before it is a runtime one. The SMS and Call Log groups, QUERY_ALL_PACKAGES, and the eight permissions barred outright from personal loan apps, read off Google's own policy pages. Read 3 September 2026.

By Shalabh D & Abhinav A
September 3, 20264 min read

Google Play's restricted-permission rules are written against what your app declares. The declaration Google reads is the merged manifest of the artefact you uploaded, not the manifest in your source tree and not the set of APIs your code calls.

Most permission advice is about runtime: request it when you need it, explain why, handle the refusal. None of that will keep an app on the store.

Read 3 September 2026, from Google's policy pages.

The sentence that makes it a build question

Under the SMS and Call Log restrictions, after the table of permission groups:

"Apps lacking default SMS, Phone, or Assistant handler capability may not declare use of the above permissions in the manifest. This includes placeholder text in the manifest."

The second sentence is the one that catches people. Never calling the API does not help, and neither does leaving the permission unrequested at runtime. The line may not be present at all, and Google says a placeholder still counts as one.

A runtime rule can be satisfied by a code path nobody takes. A manifest rule is satisfied only by deleting the entry.

What the two groups contain

Google sets them out as a table of restricted permissions against the requirement each carries. Both lists open with "for example", so neither is closed:

Restricted permissionRequirement
Call Log permission group: READ_CALL_LOG, WRITE_CALL_LOG, PROCESS_OUTGOING_CALLS"It must be actively registered as the default Phone or Assistant handler on the device."
SMS permission group: READ_SMS, SEND_SMS, WRITE_SMS, RECEIVE_SMS, RECEIVE_WAP_PUSH, RECEIVE_MMS"It must be actively registered as the default SMS or Assistant handler on the device."

And the condition is continuous: "apps must be actively registered as the default SMS, Phone, or Assistant handler before prompting users to accept any of the above permissions and must immediately stop using the permission when they’re no longer the default handler."

QUERY_ALL_PACKAGES and the two named tiers

Package visibility is a separate policy section on the same page, and Google names two levels of it.

Broad visibility, in Google's words: “Broad visibility is the capability of an app to have extensive (or “broad”) visibility of the installed apps (“packages”) on a device.” The restriction attaches to a target level, as the platform behaviour does: "For apps targeting API level 30 or later, broad visibility to installed apps via the QUERY_ALL_PACKAGES permission is restricted to specific use cases where awareness of and/or interoperability with any and all apps on the device are required for the app to function."

The test a reviewer applies is comparative: "You may not use QUERY_ALL_PACKAGES if your app can operate with a more targeted scoped package visibility declaration (for example, querying and interacting with specific packages instead of requesting broad visibility)."

Two further clauses close the obvious workarounds:

  • Approximating it by other means is covered too: "Use of alternative methods to approximate the broad visibility level associated with QUERY_ALL_PACKAGES permission are also restricted to user-facing core app functionality and interoperability with any apps discovered via this method."
  • And on what the resulting data may be used for: "Under no circumstances can data from the installed app inventory be sold or shared for advertising or analytics monetization."

The platform enforces its own version of this. An app targeting API level 30 or higher gets a filtered view of installed packages whether or not it asked for one. That change is in the expiry list, and it explains why a package-name check written before that boundary returns a clean answer instead of an error.

The eight that are barred outright

For one class of app there is no declaration to make: the permissions are prohibited. Google's scope sentence is narrow, and "fintech" is far broader than what it binds, so here it is in full:

"Personal loan apps, apps with the primary purpose of facilitating access to personal loans (for example, lead generators or facilitators) or lines of credit, accessory loan or credit apps (loan calculators, loan guides, etc.), and Earned Wage Access (EWA) apps are prohibited from accessing sensitive data, such as photos and contacts."

Then comes "The following permissions are prohibited", and the eight are READ_EXTERNAL_STORAGE, READ_MEDIA_IMAGES, READ_CONTACTS, ACCESS_FINE_LOCATION, READ_PHONE_NUMBERS, READ_MEDIA_VIDEO, QUERY_ALL_PACKAGES, WRITE_EXTERNAL_STORAGE.

Look at which eight. READ_MEDIA_IMAGES and READ_MEDIA_VIDEO are the modern split of the old external-storage read, so both the legacy and the current spellings appear. An app that migrated to the new constants did not leave the list. QUERY_ALL_PACKAGES is here as well as in its own policy, so a lending app has two separate reasons to care about the same line.

Why this is a question about your build graph

Every rule above is applied to a document that is assembled. The merged manifest holds what your code declares plus what every library declares, and Google cannot tell a permission contributed by a transitive dependency from one you typed.

So the answerable version of "do we have a permissions problem" is:

  1. Read the merged manifest of the artefact you ship, not AndroidManifest.xml in the app module.
  2. Attribute every <uses-permission> line to whatever contributed it. The build tooling can tell you; nobody usually asks it.
  3. For each line that appears in a policy above, establish which of three things is true: your app is the default handler and the requirement is met; the app has a documented core-functionality case; or the line came in with a dependency and nothing in your product needs it.

That third case is the common one. Two of the questions on the build handover sheet go straight at it: the third-party SDK inventory, and which of them contribute manifest entries. A tester needs those answered for the same reason a reviewer does.

Who decides

Declaration forms are submitted in Play Console and Google adjudicates them. Reading a manifest will not tell you whether your case is accepted.

Nor does it discharge a policy obligation. It establishes what your artefact declares, which is the thing every rule above is written against. On most Android codebases of any age, nobody has that written down.

About the authors

Shalabh D

Lead — Managed Security Services

Security researcher and penetration tester passionate about making the internet safer. Active CTF player, bug bounty hunter, and hands-on practitioner across web, network, and application security.

Abhinav A

Lead — VAPT & Security Assessments

Leads Security Brigade's VAPT delivery team, having progressed from Security Consultant to Team Lead. Has executed advanced penetration tests across BFSI, fintech, QSR and telecom.

Continue reading

All articles →

The manifest two authorities regulate: RBI paragraph 12(i) and Google Play's Financial Services permission list

Two instruments reach the same AndroidManifest.xml. The Reserve Bank of India (Digital Lending) Directions, 2025 name the phone resources a Digital Lending App must desist from accessing, in prose, and permit a one-time access for on-boarding/KYC with the borrower's explicit consent. Google Play's Financial Services policy names eight Android permission constants for personal loan apps. Google's SMS and Call Log rule is written on what an app declares in its manifest, and says so in terms, placeholder text included. That puts the merged manifest, and every library that contributes a uses-permission line to it, inside the question. And a named Chief Compliance Officer of the Regulated Entity certifies that data collection and storage by DLAs comply with para 12 and 13. Every quotation checked 2 September 2026.

Your Data safety form is a declaration about a binary, and the binary keeps changing

Google Play's Data safety form binds every developer with a published app. It covers data handled by third-party libraries and SDKs as well as your own code, and Google's position on who answers for it is one sentence long: you alone are responsible. That makes it one of the few store obligations you can actually check. A declaration and a merged manifest are two artefacts, and they can be read against each other. Read 3 September 2026.

Android 16 is now the submission gate: target API 36, and what the 1 November window actually is

Since 31 August 2026, Google Play has applied two requirements to two different sets of apps under one date, with two very different verbs. A new app or an app update must target Android 16 (API level 36) or higher to be submitted. An app already on Play must target Android 15 (API level 35) or higher to stay available to new users on newer devices. A team that has not shipped an update since it moved to API 35 is compliant on availability and blocked on submission the moment it tries to ship. Checked 2 September 2026.