BasicManageProfile申请设备管理user的流程分析
2017-10-24 09:16
706 查看
上篇双开中提及了BasicManagedProfile demo,本文分析下demo中申请manage profile user的流程
development/samples/browseable/BasicManagedProfile/src/com/example/android/basicmanagedprofile/SetupProfileFragment.java
源码位于packages/apps/ManagedProvisioning,这个apk个人理解是DevicePolicyManager的UI层面。
mUi实际上是PreProvisioningActivity
这里先看下createProfile
该方法就是调用UserManager创建了profile user,接下来走到setUpUserOrProfile
代码行数不多是因为基本每一行都是另一个方法的调用,其实做了大量的工作,整个app中到处使用的缩写mdm,展开是mobile device management application (MDM).
最终切换到刚创建的用户,整个流程结束。
从整个流程看PackageManagerService,ActivityManagerService,UserManagerService和DevicePolicyManager几个之间耦合的挺紧的,例如代码中AsUser为后缀的的各种方法肯定和UserManagerService相关;切换、启动,停止用户代码却不在UserManagerService中,而是在ActivityManagerService中;用户切换app的控制要通过PackageManagerService来完成;PackageManagerService最核心的工作是创建一个profile
user。要想彻底搞懂它们之间的关系,四个服务都要看呀,想想PackageManagerService.java就有21000+行...感到压力山大
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+行...感到压力山大
相关文章推荐
- 代码流程分析二:Settings-蓝牙分析-搜索设备原理
- pms包管理服务分析-apk卸载流程
- ios basic:1.1 design a user interface(学习在stoaryboard上build and manage views )
- 设备申请审批流程(WF实例)(转载)
- Android程序包管理机制解析和PMS启动流程分析
- 块设备的读流程分析
- “User Profile Service未能登录“问题分析对策总汇
- 代码流程分析二:Settings-蓝牙分析-点击配对连接设备原理分析
- 从USB设备插上到驱动probe调用流程分析
- Linux设备驱动模型框架分析(六)——LDDM的设备管理:uevent,mdev
- Linux 内核文件系统与设备操作流程分析
- 块设备的读流程分析
- Validation of basic field types in a user profile form
- Linux 内核文件系统与设备操作流程分析
- 字符设备管理机制分析(一)
- USB设备Firmware基本流程分析
- 设备申请审批流程(WF实例)
- ATECC508A芯片开发笔记(六):产生CSR以及申请证书(X.509)流程及其内容分析
- rt-thread的IO设备管理系统源码分析
- 【Shiro权限管理】15.Shiro授权流程分析