Suivi du code source des autorisations d'exécution
Android 8.1.0
Code de fenêtre contextuelle lors de la demande d'autorisation
Lorsque l'application utilise requestPermissions pour demander des autorisations, le système affiche une fenêtre de sélection d'autorisation.
Le code source se trouve dans le fichier packages/apps/PackageInstaller/.
GrantPermissionsActivity.java est une fenêtre contextuelle pour l'attribution des autorisations. GrantPermissionsDefaultViewHandler est utilisé pour contrôler la vue de l'interface utilisateur de GrantPermissionsActivity.
Les événements de clic de bouton sont gérés via l'interface GrantPermissionsViewHandler.ResultListener, qui est implémenté par GrantPermissionsActivity
public class GrantPermissionsActivity extends OverlayTouchActivity
implements GrantPermissionsViewHandler.ResultListener {
mViewHandler = new com.android.packageinstaller.permission.ui.handheld
.GrantPermissionsViewHandlerImpl(this, getCallingPackage())
.setResultListener(this);
}
GrantPermissionsActivity.java
appelle groupState.mGroup.grantRuntimePermissions pour obtenir des autorisations, mGroup est un objet AppPermissionGroup.java et le processus d'implémentation de grantRuntimePermissions sera décrit ultérieurement.
Parlons d'abord de l'interface utilisateur dans la fenêtre de demande d'autorisation, telle que l'affichage "Voulez-vous autoriser xx à passer des appels et à gérer les appels ?" Ce texte doit appeler
l'updateUi de GrantPermissionsViewHandlerImpl pour l'affichage de l'interface
private boolean showNextPermissionGroupGrantRequest() {
final int groupCount = mRequestGrantPermissionGroups.size();
int currentIndex = 0;
for (GroupState groupState : mRequestGrantPermissionGroups.values()) {
if (groupState.mState == GroupState.STATE_UNKNOWN) {
// 应用名称
CharSequence appLabel = mAppPermissions.getAppLabel();
// groupState.mGroup.getDescription()是权限对应的中文描述
// 由AppPermissionGroup.java获取,比如“拨打电话和管理通话”
// 注意就算请求的是一个子权限,但是获取到的将是子项对应的整个组
// 比如申请android.permission.CALL_PHONE,允许后,会把它对应的整个电话组
// 权限都获取到(包含拔打电话、读取通话记录、读取手机状态和身份、修改通话记录)
Spanned message = Html.fromHtml(getString(R.string.permission_warning_template,
appLabel, groupState.mGroup.getDescription()), 0);
// Set the permission message as the title so it can be announced.
setTitle(message);
// 此updateUi会进行UI更新,比如请求权限的应用名,请求的权限对应名称,请求应用的应用图标等
mViewHandler.updateUi(groupState.mGroup.getName(), groupCount, currentIndex,Icon.createWithResource(resources, icon), message,
groupState.mGroup.isUserSet());
//......
}
}
}
La classe correspondante de mViewHandler est GrantPermissionsViewHandlerImpl.java
mMessageView = (TextView) mCurrentDesc.findViewById(R.id.permission_message);
private void updateDescription() {
// 由updateUi调用
mIconView.setImageDrawable(mGroupIcon.loadDrawable(mActivity));
mMessageView.setText(mGroupMessage); // 比如显示“要允许xx拔打电话吗?”
}
Le code de la fenêtre contextuelle s'est terminé lorsque l'autorisation est demandée ici.
Parlons ensuite de la fenêtre des autorisations d'application dans les paramètres.
Analyse de la fenêtre d'autorisation de l'application dans les paramètres
Paramètres - Applications et notifications - Informations sur l'application - xx Applications - Autorisations
Le code source de cette fenêtre est
packages/apps/PackageInstaller/src/com/android/packageinstaller/permission/ui/handheld/AppPermissionsFragment.java
// 设置的权限窗口中改变某应用的权限时,会触发此函数
public boolean onPreferenceChange(final Preference preference, Object newValue) {
// 只展试部分关键代码
// key是权限,比如android.permission.CALL_PHONE
PermissionInfo permInfo = pm.getPermissionInfo(key, 0);
// AppPermissions mAppPermissions
final AppPermissionGroup title_group
= mAppPermissions.getPermissionGroup(permInfo.group);
if (newValue == Boolean.TRUE) {
title_group.grantRuntimePermissions(false, filterPermissions); // 取得权限
} else {
title_group.revokeRuntimePermissions(false, filterPermissions); // 取消权限
}
}
Le mAppPermissions ci-dessus est l'objet AppPermissions
title_group est fourni par mAppPermissions dans le code AppPermissions.java
La classe AppPermissionGroup est utilisée dans la fenêtre contextuelle d'autorisation de demande et l'autorisation de demande d'interface utilisateur d'autorisation dans les paramètres, et la fonction grantRuntimePermissions de la classe est appelée.
AppPermissionGroup
packages/apps/PackageInstaller/src/com/android/packageinstaller/permission/model/AppPermissions.java
// 在构造时在loadPermissionGroups初始化AppPermissionGroup数组
public AppPermissions(Context context, PackageInfo packageInfo, String[] filterPermissions,
boolean sortGroups, Runnable onErrorCallback) {
mContext = context;
mPackageInfo = packageInfo;
mFilterPermissions = filterPermissions;
mAppLabel = BidiFormatter.getInstance().unicodeWrap(
packageInfo.applicationInfo.loadSafeLabel(
context.getPackageManager()).toString());
mSortGroups = sortGroups;
mOnErrorCallback = onErrorCallback;
loadPermissionGroups(); // 调用addPermissionGroupIfNeeded
}
private void addPermissionGroupIfNeeded(String permission) {
if (getGroupForPermission(permission) != null) {
return;
}
// AppPermissionGroup对应AppPermissionGroup.java
AppPermissionGroup group = AppPermissionGroup.create(mContext,
mPackageInfo, permission);
if (group == null) {
return;
}
mGroups.add(group);
}
title_group correspond à AppPermissionGroup.java, et AppPermissionGroup.grantRuntimePermissions est appelé dans cette fonction
private final PackageManager mPackageManager;
mPackageManager.grantRuntimePermission(mPackageInfo.packageName,permission.getName(), mUserHandle);
// 会跳到PackageManger中, 最终调用到PMS中
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
```java
@Override
public void grantRuntimePermission(String packageName, String name, final int userId) {
grantRuntimePermission(packageName, name, userId, false /* Only if not fixed by policy */);
}
L'autorisation obtenue par l'autorisation d'exécution sera
mise à jour dans ce fichier /data/system/users/0/runtime-permissions.xml via private void writePermissionsSync(int userId)
. Pour une application, l'autorisation du groupe téléphonique n'est pas autorisée comme suit
<pkg name="com.android.sdk23ApiTest.wangyong">
<item name="android.permission.READ_CALL_LOG" granted="false" flags="1" />
<item name="android.permission.READ_PHONE_STATE" granted="false" flags="1" />
<item name="android.permission.CALL_PHONE" granted="false" flags="1" />
<item name="android.permission.WRITE_CALL_LOG" granted="false" flags="1" />
</pkg>
Après avoir autorisé l'autorisation du groupe téléphonique, cela devient comme ceci
<pkg name="com.android.sdk23ApiTest.wangyong">
<item name="android.permission.READ_CALL_LOG" granted="true" flags="0" />
<item name="android.permission.READ_PHONE_STATE" granted="true" flags="0" />
<item name="android.permission.CALL_PHONE" granted="true" flags="0" />
<item name="android.permission.WRITE_CALL_LOG" granted="true" flags="0" />
</pkg>
Les versions antérieures à Android 6 sont enregistrées dans le fichier de configuration data/system/packages.xml, et le code de l'ancienne version ne sera pas analysé.
Auteur : Trop beau pour sortir et refuser de réimprimer