BasicManageProfile申请设备管理user的流程分析

来源:互联网 发布:mac磁盘已被锁定 编辑:程序博客网 时间:2024/06/07 20:17

上篇双开中提及了BasicManagedProfile demo,本文分析下demo中申请manage profile user的流程

development/samples/browseable/BasicManagedProfile/src/com/example/android/basicmanagedprofile/SetupProfileFragment.java

    private void provisionManagedProfile() {        ...        Intent intent = new Intent(ACTION_PROVISION_MANAGED_PROFILE);        intent.putExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME,                        activity.getApplicationContext().getPackageName());        ...            startActivityForResult(intent, REQUEST_PROVISION_MANAGED_PROFILE);        ...    }
demo中的代码特别简单,就是发送intent就完了。后续流程会跳转到ManagedProvisioning.apk

源码位于packages/apps/ManagedProvisioning,这个apk个人理解是DevicePolicyManager的UI层面。

        <activity            android:name=".uiflows.PreProvisioningActivity"            android:excludeFromRecents="true"            android:immersive="true"            android:launchMode="singleTop"            android:theme="@style/SetupWorkSpaceTheme">            <intent-filter android:priority="10">                <action android:name="android.app.action.PROVISION_MANAGED_PROFILE" />                <action android:name="android.app.action.PROVISION_MANAGED_USER" />                <action android:name="android.app.action.PROVISION_MANAGED_DEVICE" />                <action android:name="android.app.action.PROVISION_MANAGED_SHAREABLE_DEVICE" />                <category android:name="android.intent.category.DEFAULT" />            </intent-filter>        </activity>
从AndroidManifest中看到入口在PreProvisioningActivity

    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        mController = new PreProvisioningController(                this,                this);        mController.initiateProvisioning(getIntent(), getCallingPackage());    }
跳转到PreProvisioningController.java中

   public void initiateProvisioning(Intent intent, String callingPackage) {        ...        mIsProfileOwnerProvisioning = mUtils.isProfileOwnerAction(mParams.provisioningAction);        ...        // Initiate the corresponding provisioning mode        if (mIsProfileOwnerProvisioning) {            initiateProfileOwnerProvisioning(intent);        } else {            initiateDeviceOwnerProvisioning(intent);        }    }
这里mIsProfileOwnerProvisioning=true

   private void initiateProfileOwnerProvisioning(Intent intent) {        mUi.initiateUi(                R.string.setup_work_profile,                R.string.setup_profile_start_setup,                R.string.company_controls_workspace,                R.string.the_following_is_your_mdm,                mParams);        // If there is already a managed profile, setup the profile deletion dialog.        int existingManagedProfileUserId = mUtils.alreadyHasManagedProfile(mContext);        if (existingManagedProfileUserId != -1) {            ComponentName mdmPackageName = mDevicePolicyManager                    .getProfileOwnerAsUser(existingManagedProfileUserId);            String domainName = mDevicePolicyManager                    .getProfileOwnerNameAsUser(existingManagedProfileUserId);            mUi.showDeleteManagedProfileDialog(mdmPackageName, domainName,                    existingManagedProfileUserId);        }    }
代码主要分为两部分,第一个是初始化UI,第二个是如果系统中已有manage profile user的话,会先弹出删除当前manage profile user的UI,这里看出manage profile user只可以有一个

mUi实际上是PreProvisioningActivity

 public void initiateUi(int headerRes, int titleRes, int consentRes, int mdmInfoRes,            ProvisioningParams params) {        // Setup the UI.        initializeLayoutParams(R.layout.user_consent, headerRes, false);        Button nextButton = (Button) findViewById(R.id.setup_button);        nextButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mController.afterNavigateNext();            }        });        ...    }
全部是UI的初始化代码,这个时候Activity就会等待用户点击唯一的按键继续后续流程

    public void afterNavigateNext() {        ...            mUi.showUserConsentDialog(mParams, mIsProfileOwnerProvisioning);        ...    }
    @Override    public void showUserConsentDialog(ProvisioningParams params,            boolean isProfileOwnerProvisioning) {        UserConsentDialog dialog;        if (isProfileOwnerProvisioning) {            dialog = UserConsentDialog.newProfileOwnerInstance();        } else {            dialog = UserConsentDialog.newDeviceOwnerInstance(!params.startedByTrustedSource);        }        dialog.show(getFragmentManager(), "UserConsentDialogFragment");    }
中间又是dialog的相关代码,这个太熟悉的不贴代码了,在dailog的点击事件中进行后续处理

    @Override    public void onDialogConsent() {        ...        mController.continueProvisioningAfterUserConsent();    }
后续一路跳转会到

   @Override    public void startProfileOwnerProvisioning(ProvisioningParams params) {        Intent intent = new Intent(this, ProfileOwnerProvisioningActivity.class);        intent.putExtra(ProvisioningParams.EXTRA_PROVISIONING_PARAMS, params);        startActivityForResult(intent, PROVISIONING_REQUEST_CODE);        // Set cross-fade transition animation into the interstitial progress activity.        overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);    }
跳转到另一个Activity ProfileOwnerProvisioningActivity

    @Override    protected void onResume() {        ...        // Start service async to make sure the UI is loaded first.        final Handler handler = new Handler(getMainLooper());        handler.post(new Runnable() {            @Override            public void run() {                Intent intent = new Intent(ProfileOwnerProvisioningActivity.this,                        ProfileOwnerProvisioningService.class);                intent.putExtras(getIntent());                startService(intent);            }        });    }
在onResume中启动了进行真正工作的Service ProfileOwnerProvisioningService

    private class RunnerTask extends AsyncTask<Intent, Void, Void> {        @Override        protected Void doInBackground(Intent ... intents) {           ...                initialize(intents[0]);                startManagedProfileOrUserProvisioning();           ...        }    }
在onStartCommand中启动了自定义的异步任务

 private void startManagedProfileOrUserProvisioning() throws ProvisioningException {        ProvisionLogger.logd("Starting managed profile or user provisioning");        if(isProvisioningManagedUser()) {            mManagedProfileOrUserInfo = mUserManager.getUserInfo(mUserManager.getUserHandle());            if(mManagedProfileOrUserInfo == null) {                throw raiseError("Couldn't get current user information");            }        } else {            // Work through the provisioning steps in their corresponding order            //代码流程会走到这里,创建profile user            createProfile(getString(R.string.default_managed_profile_name));        }        if (mManagedProfileOrUserInfo != null) {                      final DeleteNonRequiredAppsTask deleteNonRequiredAppsTask; //删除新user不需要的app            final DisableInstallShortcutListenersTask disableInstallShortcutListenersTask; //禁止新user创建快捷方式            final DisableBluetoothSharingTask disableBluetoothSharingTask; //禁止蓝牙分享功能            final ManagedProfileSettingsTask managedProfileSettingsTask =                      new ManagedProfileSettingsTask(this, mManagedProfileOrUserInfo.id);             //设置SettingProvider中的MANAGED_PROFILE_CONTACT_REMOTE_SEARCH字段,该字段功能详细可见            //packages/providers/ContactsProvider/src/com/android/providers/contacts/enterprise/EnterprisePolicyGuard.java            //能控制跨user查询联系人数据库的行为。            disableInstallShortcutListenersTask = new DisableInstallShortcutListenersTask(this,                    mManagedProfileOrUserInfo.id);            disableBluetoothSharingTask = new DisableBluetoothSharingTask(                    mManagedProfileOrUserInfo.id);            // TODO Add separate set of apps for MANAGED_USER, currently same as of DEVICE_OWNER.            deleteNonRequiredAppsTask = new DeleteNonRequiredAppsTask(this,                    mParams.deviceAdminComponentName.getPackageName(),                    (isProvisioningManagedUser() ? DeleteNonRequiredAppsTask.MANAGED_USER                            : DeleteNonRequiredAppsTask.PROFILE_OWNER),                    true /* creating new profile */,                    mManagedProfileOrUserInfo.id, false /* delete non-required system apps */,                    new DeleteNonRequiredAppsTask.Callback() {                        @Override                        public void onSuccess() {                            // Need to explicitly handle exceptions here, as                            // onError() is not invoked for failures in                            // onSuccess().                            try {                                disableBluetoothSharingTask.run();                                if (!isProvisioningManagedUser()) {                                    managedProfileSettingsTask.run();                                    disableInstallShortcutListenersTask.run();                                }                                setUpUserOrProfile();                             } catch (ProvisioningException e) {                                error(e.getMessage(), e);                            } catch (Exception e) {startManagedProfileOrUserProvisioning                                error("Provisioning failed", e);                            }                            finish();                        }                        @Override                        public void onError() {                            // Raise an error with a tracing exception attached.                            error("Delete non required apps task failed.", new Exception());                            finish();                        }                    });            deleteNonRequiredAppsTask.run();        }    }

这里先看下createProfile

    private void createProfile(String profileName) throws ProvisioningException {        ProvisionLogger.logd("Creating managed profile with name " + profileName);        mManagedProfileOrUserInfo = mUserManager.createProfileForUser(profileName,                UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_DISABLED,                Process.myUserHandle().getIdentifier());        if (mManagedProfileOrUserInfo == null) {            throw raiseError("Couldn't create profile.");        }    }

该方法就是调用UserManager创建了profile user,接下来走到setUpUserOrProfile

    private void setUpUserOrProfile() throws ProvisioningException {        installMdmOnManagedProfile(); //创建BasicManagedProfile应用到新创建的user        setMdmAsActiveAdmin();  //设置BasicManagedProfile应用为当前的admin        setMdmAsManagedProfileOwner(); //设置BasicManagedProfile应用为profile user owner        if (!isProvisioningManagedUser()) {            setOrganizationColor();              setDefaultUserRestrictions();  //设置默认的限制,其实只有一条,就是不能更换壁纸            CrossProfileIntentFiltersHelper.setFilters( //使intent跨user使用的关键方法                    getPackageManager(), getUserId(), mManagedProfileOrUserInfo.id);            if (!startManagedProfile(mManagedProfileOrUserInfo.id)) { //真正切换用户的方法                throw raiseError("Could not start user in background");            }            // Wait for ACTION_USER_UNLOCKED to be sent before trying to migrate the account.            // Even if no account is present, we should not send the provisioning complete broadcast            // before the managed profile user is properly started.            if ((mUnlockedReceiver != null) && !mUnlockedReceiver.waitForUserUnlocked()) {                return; //等待user创建完毕并为解锁状态,正常状况下不会走return            }            // Note: account migration must happen after setting the profile owner.            // Otherwise, there will be a time interval where some apps may think that the account            // does not have a profile owner.            //account在user间的迁移,对于BasicManagedProfile来说accountToMigrate是null            mUtils.maybeCopyAccount(this, mParams.accountToMigrate, Process.myUserHandle(),                    mManagedProfileOrUserInfo.getUserHandle());        }    }

代码行数不多是因为基本每一行都是另一个方法的调用,其实做了大量的工作,整个app中到处使用的缩写mdm,展开是mobile device management application (MDM).

    private boolean startManagedProfile(int userId)  {        ProvisionLogger.logd("Starting user in background");        IActivityManager iActivityManager = ActivityManagerNative.getDefault();        // Register a receiver for the Intent.ACTION_USER_UNLOCKED to know when the managed profile        // has been started and unlocked.        mUnlockedReceiver = new UserUnlockedReceiver(this, userId);         //接受user启动并解锁消息的Receiver,以便后续操作        try {            return iActivityManager.startUserInBackground(userId); //切换user到刚创建的profile user        } catch (RemoteException neverThrown) {            // Never thrown, as we are making local calls.            ProvisionLogger.loge("This should not happen.", neverThrown);        }        return false;    }

最终切换到刚创建的用户,整个流程结束。

从整个流程看PackageManagerService,ActivityManagerService,UserManagerService和DevicePolicyManager几个之间耦合的挺紧的,例如代码中AsUser为后缀的的各种方法肯定和UserManagerService相关;切换、启动,停止用户代码却不在UserManagerService中,而是在ActivityManagerService中;用户切换app的控制要通过PackageManagerService来完成;PackageManagerService最核心的工作是创建一个profile user。要想彻底搞懂它们之间的关系,四个服务都要看呀,想想PackageManagerService.java就有21000+行...感到压力山大

原创粉丝点击