Been doing some Android permission research and ran across an application that - according to the AndroidManifest.xml file - only declares WRITE_EXTERNAL_STORAGE as a permission. The Android Market only reports this as well. Using the aapt tool to dump the uses-permission it also only reports the one permission.
However, in code running on the Android device (or emulator), doing the following:
PackageManager pm = getPackageManager();
List<PackageInfo> pkgList = pm.getInstalledPackages(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES);
...
PackageInfo p = pkgList.get(i); // where i is the index of the apk in question
String[] perms = p.requestedPermissions;
I get 2 permissions for this APK, READ_PHONE_STATE and the one in the manifest, WRITE_EXTERNAL_STORAGE. Looking at the "Manage Apps" screen and selecting details for this also shows the additional READ_PHONE_STATE permission.
Are there cases where permissions can be/are 'implied' (in code, by feature use, etc) that would not be required in the Android Manifest? Or put another way, why does aapt return one set of permissions and the getPackageManager().getPackageInfo() API return a different set?
EDIT:
Searching with "more better" terms discovered the answer I was looking for: Android permissions: Phone Calls: read phone state and identity
In short, APKs compiled with earlier version of the SDK did inherit some permissions for free...
As far as I know permissions must always be explicitly set in the manifest.
If an application needs access to a feature protected by a permission, it must declare that it requires that permission with a element in the manifest. Then, when the application is installed on the device, the installer determines whether or not to grant the requested permission by checking the authorities that signed the application's certificates and, in some cases, asking the user. If the permission is granted, the application is able to use the protected features. If not, its attempts to access those features will simply fail without any notification to the user.
source
The difference you are seeing I believe is due to the protectionLevel attribute on permissions. Any permissions that are set to "normal" are not required to be OK'd by the user so they just show up in the Details section.
Related
In Android 0, apps that want the capability of installing apk's must be specifically granted that permission by the user in the system settings. However, I havent been able to figure out how to get my app into the list of apps the user can pick from.
Can anyone point me in the right direction?
Thanks
Probably this blog post will help:
https://android-developers.googleblog.com/2017/08/making-it-safer-to-get-apps-on-android-o.html
To sum it up:
Need to declare the permission in your manifest <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
Before install you should check if the permission is still granted (PackageManager.canRequestPackageInstalls()), if not you can request it again using
Intent intent = new Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES);
intent.setData(Uri.parse("package:YOURPACKAGENAME"));
I'm testing my app on an emulator. I have an export function where I create and write to a file in the external storage's downloads directory. And I also have an import function where I read a file from the external storage's downloads directory.
From Android documentation:
If the device is running Android 5.1 or lower, or your app's target SDK is 22 or lower: If you list a dangerous permission in your manifest, the user has to grant the permission when they install the app; if they do not grant the permission, the system does not install the app at all.
If the device is running Android 6.0 or higher, and your app's target SDK is 23 or higher: The app has to list the permissions in the manifest, and it must request each dangerous permission it needs while the app is running. The user can grant or deny each permission, and the app can continue to run with limited capabilities even if the user denies a permission request.
My emulator is running on Android 6.0 and my app's target SDK is 25, therefore I must also request each dangerous permission it needs while the app is running. I did so for the export functionality and everything works properly. However, when I'm implementing the import function I didn't request a permission during runtime. And the strange thing is I'm still able to read from my external storage's permission without READ_EXTERNAL_STORAGE being requested and granted at runtime. READ_EXTERNAL_STORAGE is a dangerous permission according to this Android documentation .
To verify, I made sure to disable permissions before I started using the feature and after it is completed, I verified again that the permission still wasn't granted. Although I'm happy with the behaviour since it's working without me requesting permission at runtime, but according to the documentations I don't believe this behaviour is expected. That's why I will like to know what's causing this and to figure out the problem before I publish any changes for the app.
Here's a code snippet of my manifest:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
The code snippet where I pick a file to read:
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("text/*");
startActivityForResult(intent, GET_FILE_RESULT_CODE);
The code snippet where I read the file chosen from the code snippet above (exportFile is simply the URI from onActivityResult):
BufferedReader br;
try {
br = new BufferedReader(new InputStreamReader(context.getContentResolver().openInputStream(exportFile)));
String line;
// Skip first header line
br.readLine();
while ((line = br.readLine()) != null) {...}
Thanks!
There's a well explanation here,
READ_EXTERNAL_STORAGE
Provides protected read access to external storage. In Android 4.1 by
default all applications still have read access. This will be changed
in a future release to require that applications explicitly request
read access using this permission. If your application already
requests write access, it will automatically get read access as well.
There is a new developer option to turn on read access restriction,
for developers to test their applications against how Android will
behave in the future.
In short, READ_EXTERNAL_STORAGE only exists as of Jelly Bean (Level 16). So, unless you're using a Jelly Bean phone and set the developer option "Protect USB storage" it won't be a problem.
You know,Android Runtime Permissions are grouped, since you applied for WRITE_EXTERNAL_STORAGE permission in the manifest already, so there's no need to apply for READ_EXTERNAL_STORAGE permissions.Both of them are the same group.
I've a problem with content provider and custom permissions.
Let's suppose that App A have a content provider containing wonderful informations. These informations are a little bit intrusive, that's why it's better to have a permission to read them.
Let's suppose that App B is a 3rd party application and want to access to the content provider of A.
Let's suppose that the permission to read into the content provider is "com.custom.a.readpermission".
In A manifest, there is :
<permission android:name="com.custom.a.readpermission"/>
<provider android:name="com.a.provider.MyProvider"
android:exported="true"
android:authorities="com.a.provider.MyProvider"
android:readPermission="com.custom.a.readpermission"/>
In B manifest, there is :
<uses-permission android:name="com.custom.a.readpermission"/>
So, now, if I install A; after, I install B. B can access to the data.
But, if I install B before A, I get :
java.lang.SecurityException: Permission Denial: opening provider com.a.provider.MyProvider requires com.custom.a.readpermission
So, how to manage a custom permission in that case ?
So, how to manage a custom permission in that case ?
Your primary options are:
Use a built-in system permission, as opposed to a custom one. This is a good idea in general, if the nature of the sensitive data is similar to other data already defended by built-in permissions.
Catch this exception and tell the user that they need to uninstall A and B and install them in the proper order.
If A and B are both by the same author, use a protectionLevel signature permission and have the same <permission> element in both A and B. Then the installation order will not matter, and the user won't be bothered with any prompts to agree to this permission.
However, bear in mind that prior to Android 5.0, the fact that option #3 works means that any app installed before A could do the same thing as B does, except downgrading the protectionLevel from signature to normal. This is a known vulnerability. Android 5.0 requires that custom permissions are defined on a "first one in wins" basis, and the second and subsequent apps trying to define the same <permission> have to be signed by the same signing key as the app that actually did define it.
In truth, permissions are great for pre-installed apps and the OS itself, but defining custom permissions at the app level is... less than great.
I am getting list of packages using packagemanager with GET_UNINSTALLED_PACKAGES flag,
PackageManager pm = getPackageManager();
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
but since it returns: "information about all applications (even uninstalled ones) which have data directories." I am unable to get reliable list of previously uninstalled package including apps that didn't left a data directory behind.
Is there any way to achieve this?
Disclaimer : I didn't try this solution, but it may help (requires Android 5)
With android 5, there is this new API : UsageStatsManager with this method :
usageStatsManager.queryAndAggregateUsageStats(startTime,endTime)
returning an Map where keys are the package name (and values are usage statistics). Hopefully, this will include uninstalled apps (but I'm not sure !). Of course you won't get the AppInfo (only the package name)
Note also this important remark about required permissions:
NOTE: This API requires the permission android.permission.PACKAGE_USAGE_STATS, which is a system-level permission and will not be granted to third-party apps. However, declaring the permission implies intention to use the API and the user of the device can grant permission through the Settings application.
This is my first time posting here. I'm not sure if this is the right place to ask this question, but I don't seem to find other more appropriate places. Here's my question anyways.
I understand that the API ActivityManager.forceStopPackage() is an internal one and can be called only from system process. However, it puzzles me that the built-in Task Manager app (with package name com.motorola.PerformanceManager) on my motorola atrix phone can directly call it without being a system process. There are two things that I verified.
First, it is non-system process from ps command:
app_64 13681 1379 170788 29820 ffffffff 00000000 S com.motorola.PerformanceManager
Second, it indeed calls the ActivityManager.forceStopPackage() API from its odex file (decompiled into smali, then into dex, and then into java). From the smali code, it is already clear that it calls this API.
I also checked its AndroidManifest.xml file which seems nothing special to me (the forum mistakenly recognizes the content as URLs and prevents me from posting them).
The manifest file does include the android.permission.FORCE_STOP_PACKAGES permission which is supposed to be a system one. A non-system app will still get permission denial error even with this permission. I tried using reflection to access this API with android.permission.FORCE_STOP_PACKAGES permission but still get the runtime error.
Now, how can the built-in Task Manager app call the internal API without being a system process.
One possibility is that the app is signed with the same platform private key. However, I'm not sure how I can verify that. Further, it is still supposed to be a system process with additional descriptions in the manifest file.
Hope someone can answer my question. Thanks.
The "android.permission.FORCE_STOP_PACKAGES" permission is protected by the platform signature.
If you have Android source code then check the declaration of the permission:
/frameworks/base/core/res/AndroidManifest.xml
...
<permission android:name="android.permission.FORCE_STOP_PACKAGES"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature"
...
You can see its protection level is signature, then check the SDK documentation for the explaination:
"android:protectionLevel"
http://developer.android.com/guide/topics/manifest/permission-element.html#plevel
"signature...A permission that the system grants only if the requesting application is signed with the same certificate as the application that declared the permission. If the certificates match, the system automatically grants the permission without notifying the user or asking for the user's explicit approval"
The permission is declared by the framework-res which is signed by the platform signature, so the application that wants to use the permission shall also be signed with the same signature.
/frameworks/base/core/res/Android.mk
...
LOCAL_PACKAGE_NAME := framework-res
LOCAL_CERTIFICATE := platform
...
Regards
Ziteng Chen