当前位置:   article > 正文

Android权限系统(二):开机授予运行时权限_defaultpermissiongrantpolicy

defaultpermissiongrantpolicy

DefaultPermissionGrantPolicy简介

  Android开机后,除了根据上次开机的记录(runtime-permissions.xml)授予运行时权限外,一些系统重要的组件也需要提前授予运行时权限,最常见的时为系统重要功能的默认组件提前授予运行时权限,例如系统会为默认的浏览器提前授予位置相关的运行时权限。而这些授权操作,是在DefaultPermissionGrantPolicy类里面进行的。DefaultPermissionGrantPolicy在PermissionManagerService的构造函数中被创建。
  默认应用的设置可以在设置-应用和通知-默认应用中找到。

frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

    PermissionManagerService(Context context,
            @NonNull Object externalLock) {
        ...

        mDefaultPermissionGrantPolicy = new DefaultPermissionGrantPolicy(
                context, mHandlerThread.getLooper(), this);

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  在PMS的systemReady阶段中,会调用DefaultPermissionGrantPolicy#grantDefaultPermissions为每一个修改过运行时权限的userid提前授予运行时权限(创建新用户也会触发授权,此处略过):

frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

    @Override
    public void systemReady() {
        ...
        // If we upgraded grant all default permissions before kicking off.
        for (int userId : grantPermissionsUserIds) {
            mDefaultPermissionPolicy.grantDefaultPermissions(userId);
        }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  提前授权的步骤分三步:1.系统特权组件授权;2.系统默认组件授权;3.特定文件指定授权。

frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java

    public void grantDefaultPermissions(int userId) {
        grantPermissionsToSysComponentsAndPrivApps(userId);
        grantDefaultSystemHandlerPermissions(userId);
        grantDefaultPermissionExceptions(userId);
        synchronized (mLock) {
            mDefaultPermissionsGrantedUsers.put(userId, userId);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

grantPermissionsToSysComponentsAndPrivApps系统特定组件授权

  首先列出主用户下所有已安装的包,过滤掉以下包:1.不支持运行时权限的(targetsdk小于M);2.没有声明申请权限的;3.不属于特权apk的;4.如果是属于更新过后的系统应用,原来的系统应用不是persistent的;5.如果不属于更新过后的系统应用,此应用不是persistent的;
6.没有系统(platform)签名的。其他包和UID小于10000(应用程序的首个UID)的包会被授予运行时权限。

frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java

    private void grantPermissionsToSysComponentsAndPrivApps(int userId) {
        Log.i(TAG, "Granting permissions to platform components for user " + userId);
        List<PackageInfo> packages = mContext.getPackageManager().getInstalledPackagesAsUser(
                DEFAULT_PACKAGE_INFO_QUERY_FLAGS, UserHandle.USER_SYSTEM);
        for (PackageInfo pkg : packages) {
            if (pkg == null) {
                continue;
            }
            if (!isSysComponentOrPersistentPlatformSignedPrivApp(pkg)
                    || !doesPackageSupportRuntimePermissions(pkg)
                    || ArrayUtils.isEmpty(pkg.requestedPermissions)) {
                continue;
            }
            grantRuntimePermissionsForSystemPackage(userId, pkg);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java

    private boolean isSysComponentOrPersistentPlatformSignedPrivApp(PackageInfo pkg) {
        if (UserHandle.getAppId(pkg.applicationInfo.uid) < FIRST_APPLICATION_UID) {
            return true;
        }
        if (!pkg.applicationInfo.isPrivilegedApp()) {
            return false;
        }
        final PackageInfo disabledPkg = getSystemPackageInfo(
                mServiceInternal.getDisabledSystemPackageName(pkg.applicationInfo.packageName));
        if (disabledPkg != null) {
            ApplicationInfo disabledPackageAppInfo = disabledPkg.applicationInfo;
            if (disabledPackageAppInfo != null
                    && (disabledPackageAppInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
                return false;
            }
        } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_PERSISTENT) == 0) {
            return false;
        }
        return mServiceInternal.isPlatformSigned(pkg.packageName);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

  对于这部分符合要求的系统组件,系统的策略是尽可能授予组件需要的任何运行时权限。

frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java

    private void grantRuntimePermissionsForSystemPackage(int userId, PackageInfo pkg) {
        Set<String> permissions = new ArraySet<>();
        for (String permission : pkg.requestedPermissions) {
            final BasePermission bp = mPermissionManager.getPermission(permission);
            if (bp == null) {
                continue;
            }
            if (bp.isRuntime()) {
                permissions.add(permission);
            }
        }
        if (!permissions.isEmpty()) {
            grantRuntimePermissions(pkg, permissions, true /*systemFixed*/, userId);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

grantDefaultSystemHandlerPermissions系统默认组件授权

  系统需要相应一部分重要的intent的默认包被授予特定的运行时权限,所以就通过grantDefaultSystemHandlerPermissions为这些包授予特定的运行时权限。

frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java

    private void grantDefaultSystemHandlerPermissions(int userId) {
        Log.i(TAG, "Granting permissions to default platform handlers for user " + userId);

        final PackagesProvider locationPackagesProvider;
        final PackagesProvider locationExtraPackagesProvider;
        final PackagesProvider voiceInteractionPackagesProvider;
        final PackagesProvider smsAppPackagesProvider;
        final PackagesProvider dialerAppPackagesProvider;
        final PackagesProvider simCallManagerPackagesProvider;
        final PackagesProvider useOpenWifiAppPackagesProvider;
        final SyncAdapterPackagesProvider syncAdapterPackagesProvider;

        synchronized (mLock) {
            locationPackagesProvider = mLocationPackagesProvider;
            locationExtraPackagesProvider = mLocationExtraPackagesProvider;
            voiceInteractionPackagesProvider = mVoiceInteractionPackagesProvider;
            smsAppPackagesProvider = mSmsAppPackagesProvider;
            dialerAppPackagesProvider = mDialerAppPackagesProvider;
            simCallManagerPackagesProvider = mSimCallManagerPackagesProvider;
            useOpenWifiAppPackagesProvider = mUseOpenWifiAppPackagesProvider;
            syncAdapterPackagesProvider = mSyncAdapterPackagesProvider;
        }

        String[] voiceInteractPackageNames = (voiceInteractionPackagesProvider != null)
                ? voiceInteractionPackagesProvider.getPackages(userId) : null;
        String[] locationPackageNames = (locationPackagesProvider != null)
                ? locationPackagesProvider.getPackages(userId) : null;
        String[] locationExtraPackageNames = (locationExtraPackagesProvider != null)
                ? locationExtraPackagesProvider.getPackages(userId) : null;
        String[] smsAppPackageNames = (smsAppPackagesProvider != null)
                ? smsAppPackagesProvider.getPackages(userId) : null;
        String[] dialerAppPackageNames = (dialerAppPackagesProvider != null)
                ? dialerAppPackagesProvider.getPackages(userId) : null;
        String[] simCallManagerPackageNames = (simCallManagerPackagesProvider != null)
                ? simCallManagerPackagesProvider.getPackages(userId) : null;
        String[] useOpenWifiAppPackageNames = (useOpenWifiAppPackagesProvider != null)
                ? useOpenWifiAppPackagesProvider.getPackages(userId) : null;
        String[] contactsSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
                syncAdapterPackagesProvider.getPackages(ContactsContract.AUTHORITY, userId) : null;
        String[] calendarSyncAdapterPackages = (syncAdapterPackagesProvider != null) ?
                syncAdapterPackagesProvider.getPackages(CalendarContract.AUTHORITY, userId) : null;

        // Installer
        grantSystemFixedPermissionsToSystemPackage(
                ArrayUtils.firstOrNull(getKnownPackages(
                        PackageManagerInternal.PACKAGE_INSTALLER, userId)),
                userId, STORAGE_PERMISSIONS);

        // Verifier
        final String verifier = ArrayUtils.firstOrNull(getKnownPackages(
                PackageManagerInternal.PACKAGE_VERIFIER, userId));
        grantSystemFixedPermissionsToSystemPackage(verifier, userId, STORAGE_PERMISSIONS);
        grantPermissionsToSystemPackage(verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS);

        // SetupWizard
        grantPermissionsToSystemPackage(
                ArrayUtils.firstOrNull(getKnownPackages(
                        PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId)), userId,
                PHONE_PERMISSIONS, CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS,
                CAMERA_PERMISSIONS);

        // Camera
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(MediaStore.ACTION_IMAGE_CAPTURE, userId),
                userId, CAMERA_PERMISSIONS, MICROPHONE_PERMISSIONS, STORAGE_PERMISSIONS);

        // Sound recorder
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(
                        MediaStore.Audio.Media.RECORD_SOUND_ACTION, userId),
                userId, MICROPHONE_PERMISSIONS);

        // Media provider
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultProviderAuthorityPackage(MediaStore.AUTHORITY, userId), userId,
                STORAGE_PERMISSIONS, PHONE_PERMISSIONS);

        // Downloads provider
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultProviderAuthorityPackage("downloads", userId), userId,
                STORAGE_PERMISSIONS);

        // Downloads UI
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(
                        DownloadManager.ACTION_VIEW_DOWNLOADS, userId),
                userId, STORAGE_PERMISSIONS);

        // Storage provider
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultProviderAuthorityPackage("com.android.externalstorage.documents", userId),
                userId, STORAGE_PERMISSIONS);

        // CertInstaller
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(Credentials.INSTALL_ACTION, userId), userId,
                STORAGE_PERMISSIONS);

        // Dialer
        if (dialerAppPackageNames == null) {
            String dialerPackage =
                    getDefaultSystemHandlerActivityPackage(Intent.ACTION_DIAL, userId);
            grantDefaultPermissionsToDefaultSystemDialerApp(dialerPackage, userId);
        } else {
            for (String dialerAppPackageName : dialerAppPackageNames) {
                grantDefaultPermissionsToDefaultSystemDialerApp(dialerAppPackageName, userId);
            }
        }

        // Sim call manager
        if (simCallManagerPackageNames != null) {
            for (String simCallManagerPackageName : simCallManagerPackageNames) {
                grantDefaultPermissionsToDefaultSystemSimCallManager(
                        simCallManagerPackageName, userId);
            }
        }

        // Use Open Wifi
        if (useOpenWifiAppPackageNames != null) {
            for (String useOpenWifiPackageName : useOpenWifiAppPackageNames) {
                grantDefaultPermissionsToDefaultSystemUseOpenWifiApp(
                        useOpenWifiPackageName, userId);
            }
        }

        // SMS
        if (smsAppPackageNames == null) {
            String smsPackage = getDefaultSystemHandlerActivityPackageForCategory(
                    Intent.CATEGORY_APP_MESSAGING, userId);
            grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
        } else {
            for (String smsPackage : smsAppPackageNames) {
                grantDefaultPermissionsToDefaultSystemSmsApp(smsPackage, userId);
            }
        }

        // Cell Broadcast Receiver
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(Intents.SMS_CB_RECEIVED_ACTION, userId),
                userId, SMS_PERMISSIONS);

        // Carrier Provisioning Service
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerServicePackage(Intents.SMS_CARRIER_PROVISION_ACTION, userId),
                userId, SMS_PERMISSIONS);

        // Calendar
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackageForCategory(
                        Intent.CATEGORY_APP_CALENDAR, userId),
                userId, CALENDAR_PERMISSIONS, CONTACTS_PERMISSIONS);

        // Calendar provider
        String calendarProvider =
                getDefaultProviderAuthorityPackage(CalendarContract.AUTHORITY, userId);
        grantPermissionsToSystemPackage(calendarProvider, userId,
                CONTACTS_PERMISSIONS, STORAGE_PERMISSIONS);
        grantSystemFixedPermissionsToSystemPackage(calendarProvider, userId, CALENDAR_PERMISSIONS);

        // Calendar provider sync adapters
        grantPermissionToEachSystemPackage(
                getHeadlessSyncAdapterPackages(calendarSyncAdapterPackages, userId),
                userId, CALENDAR_PERMISSIONS);

        // Contacts
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackageForCategory(
                        Intent.CATEGORY_APP_CONTACTS, userId),
                userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);

        // Contacts provider sync adapters
        grantPermissionToEachSystemPackage(
                getHeadlessSyncAdapterPackages(contactsSyncAdapterPackages, userId),
                userId, CONTACTS_PERMISSIONS);

        // Contacts provider
        String contactsProviderPackage =
                getDefaultProviderAuthorityPackage(ContactsContract.AUTHORITY, userId);
        grantSystemFixedPermissionsToSystemPackage(contactsProviderPackage, userId,
                CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);
        grantPermissionsToSystemPackage(contactsProviderPackage, userId, STORAGE_PERMISSIONS);

        // Device provisioning
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(
                        DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId),
                userId, CONTACTS_PERMISSIONS);

        // Maps
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackageForCategory(Intent.CATEGORY_APP_MAPS, userId),
                userId, ALWAYS_LOCATION_PERMISSIONS);

        // Gallery
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackageForCategory(
                        Intent.CATEGORY_APP_GALLERY, userId),
                userId, STORAGE_PERMISSIONS);

        // Email
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackageForCategory(
                        Intent.CATEGORY_APP_EMAIL, userId),
                userId, CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS);

        // Browser
        String browserPackage = ArrayUtils.firstOrNull(getKnownPackages(
                PackageManagerInternal.PACKAGE_BROWSER, userId));
        if (browserPackage == null) {
            browserPackage = getDefaultSystemHandlerActivityPackageForCategory(
                    Intent.CATEGORY_APP_BROWSER, userId);
            if (!isSystemPackage(browserPackage)) {
                browserPackage = null;
            }
        }
        grantPermissionsToPackage(browserPackage, userId, false /* ignoreSystemPackage */,
                true /*whitelistRestrictedPermissions*/, ALWAYS_LOCATION_PERMISSIONS);

        // Voice interaction
        if (voiceInteractPackageNames != null) {
            for (String voiceInteractPackageName : voiceInteractPackageNames) {
                grantPermissionsToSystemPackage(voiceInteractPackageName, userId,
                        CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
                        PHONE_PERMISSIONS, SMS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
            }
        }

        if (ActivityManager.isLowRamDeviceStatic()) {
            // Allow voice search on low-ram devices
            grantPermissionsToSystemPackage(
                    getDefaultSystemHandlerActivityPackage(
                            SearchManager.INTENT_ACTION_GLOBAL_SEARCH, userId),
                    userId, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
        }

        // Voice recognition
        Intent voiceRecoIntent = new Intent(RecognitionService.SERVICE_INTERFACE)
                .addCategory(Intent.CATEGORY_DEFAULT);
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerServicePackage(voiceRecoIntent, userId), userId,
                MICROPHONE_PERMISSIONS);

        // Location
        if (locationPackageNames != null) {
            for (String packageName : locationPackageNames) {
                grantPermissionsToSystemPackage(packageName, userId,
                        CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
                        PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
                        SENSORS_PERMISSIONS, STORAGE_PERMISSIONS);
                grantSystemFixedPermissionsToSystemPackage(packageName, userId,
                        ALWAYS_LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
            }
        }
        if (locationExtraPackageNames != null) {
            // Also grant location permission to location extra packages.
            for (String packageName : locationExtraPackageNames) {
                grantPermissionsToSystemPackage(packageName, userId, ALWAYS_LOCATION_PERMISSIONS);
            }
        }

        // Music
        Intent musicIntent = new Intent(Intent.ACTION_VIEW)
                .addCategory(Intent.CATEGORY_DEFAULT)
                .setDataAndType(Uri.fromFile(new File("foo.mp3")), AUDIO_MIME_TYPE);
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(musicIntent, userId), userId,
                STORAGE_PERMISSIONS);

        // Home
        Intent homeIntent = new Intent(Intent.ACTION_MAIN)
                .addCategory(Intent.CATEGORY_HOME)
                .addCategory(Intent.CATEGORY_LAUNCHER_APP);
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(homeIntent, userId), userId,
                ALWAYS_LOCATION_PERMISSIONS);

        // Watches
        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH, 0)) {
            // Home application on watches

            String wearPackage = getDefaultSystemHandlerActivityPackageForCategory(
                    Intent.CATEGORY_HOME_MAIN, userId);
            grantPermissionsToSystemPackage(wearPackage, userId,
                    CONTACTS_PERMISSIONS, MICROPHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
            grantSystemFixedPermissionsToSystemPackage(wearPackage, userId, PHONE_PERMISSIONS);

            // Fitness tracking on watches
            grantPermissionsToSystemPackage(
                    getDefaultSystemHandlerActivityPackage(ACTION_TRACK, userId), userId,
                    SENSORS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS);
        }

        // Print Spooler
        grantSystemFixedPermissionsToSystemPackage(PrintManager.PRINT_SPOOLER_PACKAGE_NAME, userId,
                ALWAYS_LOCATION_PERMISSIONS);

        // EmergencyInfo
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(
                        TelephonyManager.ACTION_EMERGENCY_ASSISTANCE, userId),
                userId, CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);

        // NFC Tag viewer
        Intent nfcTagIntent = new Intent(Intent.ACTION_VIEW)
                .setType("vnd.android.cursor.item/ndef_msg");
        grantPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(nfcTagIntent, userId), userId,
                CONTACTS_PERMISSIONS, PHONE_PERMISSIONS);

        // Storage Manager
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(
                        StorageManager.ACTION_MANAGE_STORAGE, userId),
                userId, STORAGE_PERMISSIONS);

        // Companion devices
        grantSystemFixedPermissionsToSystemPackage(
                CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME, userId,
                ALWAYS_LOCATION_PERMISSIONS);

        // Ringtone Picker
        grantSystemFixedPermissionsToSystemPackage(
                getDefaultSystemHandlerActivityPackage(
                        RingtoneManager.ACTION_RINGTONE_PICKER, userId),
                userId, STORAGE_PERMISSIONS);

        // TextClassifier Service
        String textClassifierPackageName =
                mContext.getPackageManager().getSystemTextClassifierPackageName();
        if (!TextUtils.isEmpty(textClassifierPackageName)) {
            grantPermissionsToSystemPackage(textClassifierPackageName, userId,
                    PHONE_PERMISSIONS, SMS_PERMISSIONS, CALENDAR_PERMISSIONS,
                    ALWAYS_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
        }

        // Atthention Service
        String attentionServicePackageName =
                mContext.getPackageManager().getAttentionServicePackageName();
        if (!TextUtils.isEmpty(attentionServicePackageName)) {
            grantPermissionsToSystemPackage(attentionServicePackageName, userId,
                    CAMERA_PERMISSIONS);
        }

        // There is no real "marker" interface to identify the shared storage backup, it is
        // hardcoded in BackupManagerService.SHARED_BACKUP_AGENT_PACKAGE.
        grantSystemFixedPermissionsToSystemPackage("com.android.sharedstoragebackup", userId,
                STORAGE_PERMISSIONS);

        // System Captions Service
        String systemCaptionsServicePackageName =
                mContext.getPackageManager().getSystemCaptionsServicePackageName();
        if (!TextUtils.isEmpty(systemCaptionsServicePackageName)) {
            grantPermissionsToSystemPackage(systemCaptionsServicePackageName, userId,
                    MICROPHONE_PERMISSIONS);
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355

grantDefaultPermissionExceptions特定文件指定授权

  系统中{partition}/etc/default-permissions目录下的xml文件可以为特定包提前授予运行时权限。

frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java

    private void grantDefaultPermissionExceptions(int userId) {
        mHandler.removeMessages(MSG_READ_DEFAULT_PERMISSION_EXCEPTIONS);

        synchronized (mLock) {
            // mGrantExceptions is null only before the first read and then
            // it serves as a cache of the default grants that should be
            // performed for every user. If there is an entry then the app
            // is on the system image and supports runtime permissions.
            if (mGrantExceptions == null) {
                mGrantExceptions = readDefaultPermissionExceptionsLocked();
            }
        }

        Set<String> permissions = null;
        final int exceptionCount = mGrantExceptions.size();
        for (int i = 0; i < exceptionCount; i++) {
            String packageName = mGrantExceptions.keyAt(i);
            PackageInfo pkg = getSystemPackageInfo(packageName);
            List<DefaultPermissionGrant> permissionGrants = mGrantExceptions.valueAt(i);
            final int permissionGrantCount = permissionGrants.size();
            for (int j = 0; j < permissionGrantCount; j++) {
                DefaultPermissionGrant permissionGrant = permissionGrants.get(j);
                if (!isPermissionDangerous(permissionGrant.name)) {
                    Log.w(TAG, "Ignoring permission " + permissionGrant.name
                            + " which isn't dangerous");
                    continue;
                }
                if (permissions == null) {
                    permissions = new ArraySet<>();
                } else {
                    permissions.clear();
                }
                permissions.add(permissionGrant.name);


                grantRuntimePermissions(pkg, permissions, permissionGrant.fixed,
                        permissionGrant.whitelisted, true /*whitelistRestrictedPermissions*/,
                        userId);
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

  `以下是其中一个xml default-permissions-google.xml的内容。package表示要额外处理的包名,sha256-cert-digest目前还没用上,permission 的name是要提前授予的权限名称,permission的fixed表示授权后是否可以被非系统组件修改权限,permission还有个whitelisted,表示是否可以为限制权限添加限制免除标志位。

<exceptions>
  <exception
    package="com.google.android.apps.restore"
    sha256-cert-digest="56:BE:13:2B:78:06:56:FE:24:44:CD:34:32:6E:B5:D7:AA:C9:1D:20:96:AB:F0:FE:67:3A:99:27:06:22:EC:87">
    <!-- External storage -->
    <permission name="android.permission.READ_EXTERNAL_STORAGE" fixed="false"/>
    <permission name="android.permission.WRITE_EXTERNAL_STORAGE" fixed="false"/>
    <!-- Contacts -->
    <permission name="android.permission.READ_CONTACTS" fixed="false"/>
    <permission name="android.permission.WRITE_CONTACTS" fixed="false"/>
  </exception>

  <exception
    package="com.google.android.apps.assistant"
    sha256-cert-digest="43:0B:20:EB:61:96:7E:9C:5B:BE:02:59:9B:07:35:16:80:7D:AE:72:D7:86:FE:92:7F:48:96:B7:C7:F2:96:1F">
    <!-- Record audio -->
    <permission name="android.permission.RECORD_AUDIO" fixed="false"/>
  </exception>

  <exception
    package="com.google.android.projection.gearhead"
    sha256-cert-digest="FD:B0:0C:43:DB:DE:8B:51:CB:31:2A:A8:1D:3B:5F:A1:77:13:AD:B9:4B:28:F5:98:D7:7F:8E:B8:9D:AC:EE:DF">
    <permission name="android.permission.ACCESS_FINE_LOCATION" fixed="false"/>
    <permission name="android.permission.CALL_PHONE" fixed="false"/>
    <permission name="android.permission.READ_CALL_LOG" fixed="false"/>
    <permission name="android.permission.READ_CONTACTS" fixed="false"/>
    <permission name="android.permission.READ_PHONE_STATE" fixed="false"/>
    <permission name="android.permission.RECEIVE_SMS" fixed="false"/>
    <permission name="android.permission.RECORD_AUDIO" fixed="false"/>
    <permission name="android.permission.SEND_SMS" fixed="false"/>
    <permission name="android.permission.PROCESS_OUTGOING_CALLS" fixed="false"/>
    <permission name="android.permission.READ_SMS" fixed="false"/>
    <permission name="android.permission.RECEIVE_MMS" fixed="false"/>
    <permission name="android.permission.WRITE_CALL_LOG" fixed="false"/>
    <permission name="android.permission.ACCESS_COARSE_LOCATION" fixed="false"/>
  </exception>
</exceptions>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

统一授权入口grantRuntimePermissions

  无论是grantPermissionsToSystemPackage还是grantSystemFixedPermissionsToSystemPackage,还是grantPermissionsToSystemPackage。它们最终都会调用到grantRuntimePermissions,只是入参的值不一样而已。
  第一个参数pkg是包的信息封装PackageInfo对象,第二个参数permissionsWithoutSplits是未被分割(split permission)的要被授予的运行时权限,第三个参数systemFixed表示本次授予的权限是否带上系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位,以免被非系统组件修改,第四个参数ignoreSystemPackage表示授权时是否考虑放置在system分区下的原应用,第五个参数whitelistRestrictedPermissions表示是否为限制权限添加限制免除(FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT)标志位,第六个参数是要授予的运行时权限对应的userid。

frameworks/base/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java

    private void grantRuntimePermissions(PackageInfo pkg, Set<String> permissionsWithoutSplits,
            boolean systemFixed, boolean ignoreSystemPackage,
            boolean whitelistRestrictedPermissions, int userId) {
        UserHandle user = UserHandle.of(userId);
        if (pkg == null) {
            return;
        }

        String[] requestedPermissions = pkg.requestedPermissions;
        if (ArrayUtils.isEmpty(requestedPermissions)) {
            return;
        }

        // Intersect the requestedPermissions for a factory image with that of its current update
        // in case the latter one removed a <uses-permission>
        String[] requestedByNonSystemPackage = getPackageInfo(pkg.packageName).requestedPermissions;
        int size = requestedPermissions.length;
        for (int i = 0; i < size; i++) {
            if (!ArrayUtils.contains(requestedByNonSystemPackage, requestedPermissions[i])) {
                requestedPermissions[i] = null;
            }
        }
        requestedPermissions = ArrayUtils.filterNotNull(requestedPermissions, String[]::new);

        PackageManager pm;
        try {
            pm = mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
                    user).getPackageManager();
        } catch (NameNotFoundException doesNotHappen) {
            throw new IllegalStateException(doesNotHappen);
        }

        final ArraySet<String> permissions = new ArraySet<>(permissionsWithoutSplits);
        ApplicationInfo applicationInfo = pkg.applicationInfo;
       //添加默认授权(FLAG_PERMISSION_GRANTED_BY_DEFAULT)标志位
        int newFlags = PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
        if (systemFixed) {
            //添加系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位
            newFlags |= PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
        }

        // Automatically attempt to grant split permissions to older APKs
        //如果要授予的权限含有split permission,把对应的new permission也加入到授权集合中
        final List<PermissionManager.SplitPermissionInfo> splitPermissions =
                mContext.getSystemService(PermissionManager.class).getSplitPermissions();
        final int numSplitPerms = splitPermissions.size();
        for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
            final PermissionManager.SplitPermissionInfo splitPerm =
                    splitPermissions.get(splitPermNum);

            if (applicationInfo != null
                    && applicationInfo.targetSdkVersion < splitPerm.getTargetSdk()
                    && permissionsWithoutSplits.contains(splitPerm.getSplitPermission())) {
                permissions.addAll(splitPerm.getNewPermissions());
            }
        }

        Set<String> grantablePermissions = null;

        // In some cases, like for the Phone or SMS app, we grant permissions regardless
        // of if the version on the system image declares the permission as used since
        // selecting the app as the default for that function the user makes a deliberate
        // choice to grant this app the permissions needed to function. For all other
        // apps, (default grants on first boot and user creation) we don't grant default
        // permissions if the version on the system image does not declare them.
        //入参ignoreSystemPackage为false且目标包是更新过的system app的时候,则按system下面的包声明申请的权限为标准进行筛选
        if (!ignoreSystemPackage
                && applicationInfo != null
                && applicationInfo.isUpdatedSystemApp()) {
            final PackageInfo disabledPkg = getSystemPackageInfo(
                    mServiceInternal.getDisabledSystemPackageName(pkg.packageName));
            if (disabledPkg != null) {
                if (ArrayUtils.isEmpty(disabledPkg.requestedPermissions)) {
                    return;
                }
                if (!Arrays.equals(requestedPermissions, disabledPkg.requestedPermissions)) {
                    grantablePermissions = new ArraySet<>(Arrays.asList(requestedPermissions));
                    requestedPermissions = disabledPkg.requestedPermissions;
                }
            }
        }

        final int numRequestedPermissions = requestedPermissions.length;

        // Sort requested permissions so that all permissions that are a foreground permission (i.e.
        // permissions that have a background permission) are before their background permissions.
        final String[] sortedRequestedPermissions = new String[numRequestedPermissions];
        int numForeground = 0;
        int numOther = 0;
        for (int i = 0; i < numRequestedPermissions; i++) {
            String permission = requestedPermissions[i];
            if (getBackgroundPermission(permission) != null) {
                sortedRequestedPermissions[numForeground] = permission;
                numForeground++;
            } else {
                sortedRequestedPermissions[numRequestedPermissions - 1 - numOther] =
                        permission;
                numOther++;
            }
        }

        for (int requestedPermissionNum = 0; requestedPermissionNum < numRequestedPermissions;
                requestedPermissionNum++) {
            //如果是入参pkg是更新过的包且入参ignoreSystemPackage为false,这里遍历的是对应的system分区的声明申请权限;否则遍历的是目标包的声明申请权限
            String permission = requestedPermissions[requestedPermissionNum];

            // If there is a disabled system app it may request a permission the updated
            // version ot the data partition doesn't, In this case skip the permission.
            //如果存在更新包对应在system分区的包,system分区的包声明了某个权限,但是更新的data分区的包没有声明这个权限,则忽略这个权限
            if (grantablePermissions != null && !grantablePermissions.contains(permission)) {
                continue;
            }

            if (permissions.contains(permission)) {//如果包声明申请的权限在本次调用所要申请的权限集合中
                final int flags = mContext.getPackageManager().getPermissionFlags(
                        permission, pkg.packageName, user);

                // If we are trying to grant as system fixed and already system fixed
                // then the system can change the system fixed grant state.
                final boolean changingGrantForSystemFixed = systemFixed
                        && (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0;

                // Certain flags imply that the permission's current state by the system or
                // device/profile owner or the user. In these cases we do not want to clobber the
                // current state.
                //
                // Unless the caller wants to override user choices. The override is
                // to make sure we can grant the needed permission to the default
                // sms and phone apps after the user chooses this in the UI.
                //如果1.权限不是用户设置或者固定的 2.入参ignoreSystemPackage 为false 3,尝试改变带有系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位的权限状态 三个条件满足之一
                if (!isFixedOrUserSet(flags) || ignoreSystemPackage
                        || changingGrantForSystemFixed) {
                    // Never clobber policy fixed permissions.
                    // We must allow the grant of a system-fixed permission because
                    // system-fixed is sticky, but the permission itself may be revoked.
                    //如果权限带有devicepolicy固定(FLAG_PERMISSION_POLICY_FIXED)标志位,跳过该权限
                    if ((flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
                        continue;
                    }

                    // Preserve whitelisting flags.
                    //保留所有的限制免除标志位
                    newFlags |= (flags & PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT);

                    // If we are whitelisting the permission, update the exempt flag before grant.
                    //如果入参whitelistRestrictedPermissions为true,目标权限是限制权限,为该权限添加系统限制免除(FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT)标志位
                    if (whitelistRestrictedPermissions && isPermissionRestricted(permission)) {
                        mContext.getPackageManager().updatePermissionFlags(permission,
                                pkg.packageName,
                                PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT,
                                PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT, user);
                    }

                    // If the system tries to change a system fixed permission from one fixed
                    // state to another we need to drop the fixed flag to allow the grant.
                    //如果尝试为一个带系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位的权限添加系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位,先把原来的系统固定(FLAG_PERMISSION_SYSTEM_FIXED)标志位移除掉
                    if (changingGrantForSystemFixed) {
                        mContext.getPackageManager().updatePermissionFlags(permission,
                                pkg.packageName, flags,
                                flags & ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, user);
                    }

                    if (pm.checkPermission(permission, pkg.packageName)
                            != PackageManager.PERMISSION_GRANTED) {//授予权限
                        mContext.getPackageManager()
                                .grantRuntimePermission(pkg.packageName, permission, user);
                    }
                    //更新权限标志位
                    mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
                            newFlags, newFlags, user);

                    int uid = UserHandle.getUid(userId,
                            UserHandle.getAppId(pkg.applicationInfo.uid));
                    //如果目标权限是一个后台权限,遍历其对应的所有前台权限,如果对于目标包某个前台权限是授权了的,那么目标包的uid进行前台权限操作将通过appops设置成允许
                    List<String> fgPerms = mPermissionManager.getBackgroundPermissions()
                            .get(permission);
                    if (fgPerms != null) {
                        int numFgPerms = fgPerms.size();
                        for (int fgPermNum = 0; fgPermNum < numFgPerms; fgPermNum++) {
                            String fgPerm = fgPerms.get(fgPermNum);

                            if (pm.checkPermission(fgPerm, pkg.packageName)
                                    == PackageManager.PERMISSION_GRANTED) {
                                // Upgrade the app-op state of the fg permission to allow bg access
                                // TODO: Dont' call app ops from package manager code.
                                mContext.getSystemService(AppOpsManager.class).setUidMode(
                                        AppOpsManager.permissionToOp(fgPerm), uid,
                                        AppOpsManager.MODE_ALLOWED);

                                break;
                            }
                        }
                    }
                                  
                    String bgPerm = getBackgroundPermission(permission);
                    String op = AppOpsManager.permissionToOp(permission);
                    if (bgPerm == null) {//如果目标权限没有对应的后台权限,直接将权限操作通过appops设置为允许
                        if (op != null) {
                            // TODO: Dont' call app ops from package manager code.
                            mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid,
                                    AppOpsManager.MODE_ALLOWED);
                        }
                    } else {//如果目标权限有对应的后台权限,检查对应的后台权限是否授予给目标包了,有的话将权限操作通过appops设置为允许,没有的话将权限操作通过appops设置为前台允许
                        int mode;
                        if (pm.checkPermission(bgPerm, pkg.packageName)
                                == PackageManager.PERMISSION_GRANTED) {
                            mode = AppOpsManager.MODE_ALLOWED;
                        } else {
                            mode = AppOpsManager.MODE_FOREGROUND;
                        }

                        mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid, mode);
                    }

                    if (DEBUG) {
                        Log.i(TAG, "Granted " + (systemFixed ? "fixed " : "not fixed ")
                                + permission + " to default handler " + pkg);

                        int appOp = AppOpsManager.permissionToOpCode(permission);
                        if (appOp != AppOpsManager.OP_NONE
                                && AppOpsManager.opToDefaultMode(appOp)
                                        != AppOpsManager.MODE_ALLOWED) {
                            // Permission has a corresponding appop which is not allowed by default
                            // We must allow it as well, as it's usually checked alongside the
                            // permission
                            if (DEBUG) {
                                Log.i(TAG, "Granting OP_" + AppOpsManager.opToName(appOp)
                                        + " to " + pkg.packageName);
                            }
                            mContext.getSystemService(AppOpsManager.class).setUidMode(
                                    appOp, pkg.applicationInfo.uid, AppOpsManager.MODE_ALLOWED);
                        }
                    }
                }

                // If a component gets a permission for being the default handler A
                // and also default handler B, we grant the weaker grant form.
                if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) != 0
                        && (flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0
                        && !systemFixed) {
                    if (DEBUG) {
                        Log.i(TAG, "Granted not fixed " + permission + " to default handler "
                                + pkg);
                    }
                    mContext.getPackageManager().updatePermissionFlags(permission, pkg.packageName,
                            PackageManager.FLAG_PERMISSION_SYSTEM_FIXED, 0, user);
                }
            }
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/261305
推荐阅读
相关标签
  

闽ICP备14008679号