Android P, power on to authorize third-party applications

dudu 2021-09-15 08:39:22

Source of problem :

A pile of customers app preset to /system/preloadapp after , Boot pass shell Copy the script to /data/app Install the normal , Use is also normal , But the problem is that there will be a lot of bullets to confirm authorization when used for the first time , Because of the particularity of the product , The customer requires that the authorization of this preset application should not allow the user to participate , That is, all authorizations must be completed silently when starting up .

resolvent :

Wrote a separate application , Listen to the boot broadcast , Perform authorization processing when receiving the broadcast .( It was first put in Provision In the application , But the customer said it's best to check every time , So that's it )

AndroidManifext.xml

as follows :

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.servicedemo"
android:sharedUserId="android.uid.system"
coreApp="true"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="23"
android:targetSdkVersion="28" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS"/>
<uses-permission android:name="android.permission.GRANT_RUNTIME_PERMISSIONS"/>
<uses-permission android:name="android.permission.MANAGE_APP_OPS_MODES"/>
<uses-permission android:name="android.permission.GET_APP_OPS_STATS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name=".BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
</application>
</manifest>

arrays.xml: Configure the white list of applications that need authorization

as follows :

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<string-array name="app_packages">
<item>com.autonavi.amapautolite</item>
<item>ctrip.android.view</item>
<item>com.ecar.assistantnew</item>
<item>com.hdsc.edog</item>
<item>cn.kuwo.kwmusiccar</item>
<item>com.mapgoo.diruite</item>
</string-array>
</resources>

Android.mk:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := ServiceDemo
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform
LOCAL_DEX_PREOPT := false
include $(BUILD_PACKAGE)
# Use the folloing include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))

BootReceiver.java:

package com.example.servicedemo;
import java.io.File;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.app.AppOpsManager;
import android.app.AppOpsManager.PackageOps;
import android.app.AppOpsManager.OpEntry;
import android.util.Log;
import android.os.Environment;
import android.os.Process;
public class BootReceiver extends BroadcastReceiver {
private static final String TAG = "BootReceiver";
private JSONArray mFileList;
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
Log.d(TAG, "----onReceive " + intent.toString());
long stime = System.currentTimeMillis();
String[] appPackages = context.getResources().getStringArray(
R.array.app_packages);
for (String appPackage : appPackages) {
setAppPermission(appPackage, context);
}
PackageManager pm = context.getPackageManager();
boolean debugAutoGrant = false;
// This is traversal /data/app All of the following apk, according to apk Resolve the package name before authorization , It should be flawed
if (false) {
mFileList = new JSONArray();
getAllFiles("/data/app/", ".apk");
for (int i = 0; i < mFileList.length(); i++) {
try {
JSONObject jsonObject = mFileList.getJSONObject(i);
String pathString = jsonObject.getString("path");
Log.d(TAG, "-------apk path: " + pathString);
PackageInfo info = pm.getPackageArchiveInfo(pathString,
PackageManager.GET_ACTIVITIES);
if (info != null) {
ApplicationInfo appInfo = info.applicationInfo;
String appName = pm.getApplicationLabel(appInfo)
.toString();
String packname = appInfo.packageName;
String version = info.versionName;
Log.d(TAG, "-------package name: " + packname);
setAppPermission(packname, context);
} else {
Log.e(TAG, "========failed to get package info from "
+ pathString);
}
} catch (JSONException ex) {
ex.printStackTrace();
}
}
}
long etime = System.currentTimeMillis();
Log.d(TAG, "grant permission time: " + (etime - stime) + " ms");
}
// This is to get /data/app All of the following apk File path
private void getAllFiles(String dirPath, String fileType) {
Log.d(TAG, "dirPath: " + dirPath + " fileType: " + fileType);
File f = new File(dirPath);
if (!f.exists()) {
Log.e(TAG, "folder doesn't exist");
return;
}
File[] files = f.listFiles();
if (files == null) {
Log.e(TAG, "empty folder");
return;
}
for (File file : files) {
if (file.isFile() && file.getName().endsWith(fileType)) {
String name = file.getName();
String filePath = file.getAbsolutePath();
Log.d(TAG, "apk file is : " + filePath);
try {
JSONObject info = new JSONObject();
info.put("name", name);
info.put("path", filePath);
mFileList.put(info);
} catch (Exception e) {
}
} else if (file.isDirectory()) {
getAllFiles(file.getAbsolutePath(), fileType);
}
}
}
// Authorize key functions
private void setAppPermission(String pkgName, Context context) {
Log.d(TAG, "setAppPermission for package: " + pkgName);
PackageManager pm = context.getPackageManager();
AppOpsManager mAppOps = context.getSystemService(AppOpsManager.class);
try {
PackageInfo pkgInfo = pm.getPackageInfo(pkgName,
PackageManager.GET_PERMISSIONS);
String sharedPkgList[] = pkgInfo.requestedPermissions;
for (int i = 0; i < sharedPkgList.length; i++) {
String permName = sharedPkgList[i];
PermissionInfo permissionInfo;
try {
permissionInfo = pm.getPermissionInfo(permName, 0);
} catch (PackageManager.NameNotFoundException e) {
continue;
}
final int opCode = AppOpsManager.permissionToOpCode(permName);
boolean hasAopsCode = opCode > AppOpsManager.OP_NONE
&& opCode < AppOpsManager._NUM_OP;
String aopStr = AppOpsManager.permissionToOp(permName);
boolean hasAopsOp = aopStr != null;
boolean onlyAops = false;
final boolean granted = (pkgInfo.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
if ((permissionInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) != PermissionInfo.PROTECTION_DANGEROUS
|| (permissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0
|| (permissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0) {
if (permName.startsWith("android.")
&& (hasAopsCode || hasAopsOp)) {
onlyAops = true;
Log.d(TAG, "permissionName=" + permName + ",opCode="
+ opCode);
} else {
continue;
}
}
boolean isAopsAllowed = mAppOps.checkOpNoThrow(opCode,
pkgInfo.applicationInfo.uid, pkgInfo.packageName) == AppOpsManager.MODE_ALLOWED;
if ((hasAopsCode || onlyAops) && !isAopsAllowed) {
mAppOps.setMode(opCode, pkgInfo.applicationInfo.uid,
pkgInfo.packageName, AppOpsManager.MODE_ALLOWED);
}
if ((hasAopsOp || onlyAops) && !isAopsAllowed) {
mAppOps.setUidMode(aopStr, pkgInfo.applicationInfo.uid,
AppOpsManager.MODE_ALLOWED);
}
if (!granted && !onlyAops) {
Log.d(TAG, "grant permission " + permName + " to pkg: "
+ pkgName);
pm.grantRuntimePermission(pkgName, permName,
Process.myUserHandle());
}
// set flags
pm.updatePermissionFlags(
permName,
pkgName,
PackageManager.FLAG_PERMISSION_USER_FIXED
| PackageManager.FLAG_PERMISSION_USER_SET
| PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED,
0, Process.myUserHandle());
}
List<AppOpsManager.PackageOps> ops = mAppOps.getOpsForPackage(
pkgInfo.applicationInfo.uid, pkgName, null);
if (ops == null || ops.size() == 0) {
return;
}
for (PackageOps packageOps : ops) {
List<OpEntry> entries = packageOps.getOps();
if (entries == null || entries.size() == 0) {
continue;
}
for (OpEntry opEntry : entries) {
mAppOps.setMode(opEntry.getOp(), packageOps.getUid(),
pkgName, AppOpsManager.MODE_ALLOWED);
}
}
} catch (Exception e) {
Log.e(TAG, "setAppPermission exception, the packageName is "
+ pkgName);
e.printStackTrace();
}
}
}

other :

Pass the white list authorization test .
It also tests the traversal /data/app Next apk, According to apk Resolve the package name for authorization , Actually, there will be a problem . individual apk Unable to resolve package name , Therefore, authorization confirmation cannot be made . The code is reserved for reference .

Reference resources :

https://www.cxyzjd.com/articl...
Refer to the above article , Complete other details (manifest、 White list mechanism 、mk Documents, etc. )

Please bring the original link to reprint ,thank
Similar articles

2021-09-15

2021-09-15