• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.managedprovisioning;
18 
19 import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE;
20 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
21 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
22 import static android.Manifest.permission.BIND_DEVICE_ADMIN;
23 
24 import android.app.Activity;
25 import android.app.ActivityManagerNative;
26 import android.app.IActivityManager;
27 import android.app.Service;
28 import android.app.admin.DevicePolicyManager;
29 import android.content.BroadcastReceiver;
30 import android.content.ComponentName;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.IntentFilter;
34 import android.content.pm.ActivityInfo;
35 import android.content.pm.IPackageManager;
36 import android.content.pm.PackageInfo;
37 import android.content.pm.PackageManager;
38 import android.content.pm.PackageManager.NameNotFoundException;
39 import android.content.pm.UserInfo;
40 import android.os.AsyncTask;
41 import android.os.Parcelable;
42 import android.os.PersistableBundle;
43 import android.os.IBinder;
44 import android.os.Process;
45 import android.os.RemoteException;
46 import android.os.ServiceManager;
47 import android.os.UserHandle;
48 import android.os.UserManager;
49 import android.provider.MediaStore;
50 import android.provider.Settings;
51 import android.support.v4.content.LocalBroadcastManager;
52 import android.text.TextUtils;
53 
54 import com.android.managedprovisioning.CrossProfileIntentFiltersHelper;
55 import com.android.managedprovisioning.task.DeleteNonRequiredAppsTask;
56 
57 /**
58  * Service that runs the managed provisioning.
59  *
60  * <p>This service is started from and sends updates to the {@link ManagedProvisioningActivity},
61  * which contains the provisioning UI.
62  */
63 public class ManagedProvisioningService extends Service {
64 
65     // Intent actions for communication with DeviceOwnerProvisioningService.
66     public static final String ACTION_PROVISIONING_SUCCESS =
67             "com.android.managedprovisioning.provisioning_success";
68     public static final String ACTION_PROVISIONING_ERROR =
69             "com.android.managedprovisioning.error";
70     public static final String EXTRA_LOG_MESSAGE_KEY = "ProvisioingErrorLogMessage";
71 
72     private String mMdmPackageName;
73     private ComponentName mActiveAdminComponentName;
74 
75     // PersistableBundle extra received in starting intent.
76     // Should be passed through to device management application when provisioning is complete.
77     private PersistableBundle mAdminExtrasBundle;
78 
79     private IPackageManager mIpm;
80     private UserInfo mManagedProfileUserInfo;
81     private UserManager mUserManager;
82 
83     private int mStartIdProvisioning;
84     private AsyncTask<Intent, Object, Void> runnerTask;
85 
86     private class RunnerTask extends AsyncTask<Intent, Object, Void> {
87         @Override
doInBackground(Intent .... intents)88         protected Void doInBackground(Intent ... intents) {
89             initialize(intents[0]);
90             startManagedProfileProvisioning();
91             return null;
92         }
93     }
94 
95     @Override
onCreate()96     public void onCreate() {
97         super.onCreate();
98 
99         ProvisionLogger.logd("Managed provisioning service ONCREATE");
100 
101         mIpm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
102         mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
103 
104         runnerTask = new RunnerTask();
105     }
106 
107     @Override
onStartCommand(final Intent intent, int flags, int startId)108     public int onStartCommand(final Intent intent, int flags, int startId) {
109 
110         ProvisionLogger.logd("Starting managed provisioning service");
111         try {
112             runnerTask.execute(intent);
113         } catch (IllegalStateException ex) {
114             ProvisionLogger.logd("ManagedProvisioningService: Provisioning already in progress, "
115                     + "second provisioning intent not being processed");
116         }
117         return START_NOT_STICKY;
118     }
119 
initialize(Intent intent)120     private void initialize(Intent intent) {
121         mMdmPackageName = intent.getStringExtra(EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME);
122 
123         // Cast is guaranteed by check in Activity.
124         mAdminExtrasBundle  = (PersistableBundle) intent.getParcelableExtra(
125                 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE);
126 
127         mActiveAdminComponentName = getAdminReceiverComponent(mMdmPackageName);
128     }
129 
130     /**
131      * Find the Device admin receiver component from the manifest.
132      */
getAdminReceiverComponent(String packageName)133     private ComponentName getAdminReceiverComponent(String packageName) {
134         ComponentName adminReceiverComponent = null;
135 
136         try {
137             PackageInfo pi = getPackageManager().getPackageInfo(packageName,
138                     PackageManager.GET_RECEIVERS);
139             for (ActivityInfo ai : pi.receivers) {
140                 if (!TextUtils.isEmpty(ai.permission) &&
141                         ai.permission.equals(BIND_DEVICE_ADMIN)) {
142                     adminReceiverComponent = new ComponentName(packageName, ai.name);
143 
144                 }
145             }
146         } catch (NameNotFoundException e) {
147             error("Error: The provided mobile device management package does not define a device"
148                     + "admin receiver component in its manifest.");
149         }
150         return adminReceiverComponent;
151     }
152 
153     /**
154      * This is the core method of this class. It goes through every provisioning step.
155      */
startManagedProfileProvisioning()156     private void startManagedProfileProvisioning() {
157 
158         ProvisionLogger.logd("Starting managed profile provisioning");
159 
160         // Work through the provisioning steps in their corresponding order
161         createProfile(getString(R.string.default_managed_profile_name));
162         if (mManagedProfileUserInfo != null) {
163             new DeleteNonRequiredAppsTask(this,
164                     mMdmPackageName, mManagedProfileUserInfo.id,
165                     R.array.required_apps_managed_profile,
166                     R.array.vendor_required_apps_managed_profile,
167                     true /* We are creating a new profile */,
168                     true /* Disable INSTALL_SHORTCUT listeners */,
169                     new DeleteNonRequiredAppsTask.Callback() {
170 
171                         @Override
172                         public void onSuccess() {
173                             setUpProfileAndFinish();
174                         }
175 
176                         @Override
177                         public void onError() {
178                             error("Delete non required apps task failed.");
179                         }
180                     }).run();
181         }
182     }
183 
184     /**
185      * Called when the new profile is ready for provisioning (the profile is created and all the
186      * apps not needed have been deleted).
187      */
setUpProfileAndFinish()188     private void setUpProfileAndFinish() {
189             installMdmOnManagedProfile();
190             setMdmAsActiveAdmin();
191             setMdmAsManagedProfileOwner();
192             startManagedProfile();
193             CrossProfileIntentFiltersHelper.setFilters(
194                     getPackageManager(), getUserId(), mManagedProfileUserInfo.id);
195             onProvisioningSuccess(mActiveAdminComponentName);
196     }
197 
createProfile(String profileName)198     private void createProfile(String profileName) {
199 
200         ProvisionLogger.logd("Creating managed profile with name " + profileName);
201 
202         mManagedProfileUserInfo = mUserManager.createProfileForUser(profileName,
203                 UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_DISABLED,
204                 Process.myUserHandle().getIdentifier());
205 
206         if (mManagedProfileUserInfo == null) {
207             if (UserManager.getMaxSupportedUsers() == mUserManager.getUserCount()) {
208                 error("Profile creation failed, maximum number of users reached.");
209             } else {
210                 error("Couldn't create profile. Reason unknown.");
211             }
212         }
213     }
214 
215     /**
216      * Initializes the user that underlies the managed profile.
217      * This is required so that the provisioning complete broadcast can be sent across to the
218      * profile and apps can run on it.
219      */
startManagedProfile()220     private void startManagedProfile()  {
221         ProvisionLogger.logd("Starting user in background");
222         IActivityManager iActivityManager = ActivityManagerNative.getDefault();
223         try {
224             boolean success = iActivityManager.startUserInBackground(mManagedProfileUserInfo.id);
225             if (!success) {
226                error("Could not start user in background");
227             }
228         } catch (RemoteException neverThrown) {
229             // Never thrown, as we are making local calls.
230             ProvisionLogger.loge("This should not happen.", neverThrown);
231         }
232     }
233 
installMdmOnManagedProfile()234     private void installMdmOnManagedProfile() {
235 
236         ProvisionLogger.logd("Installing mobile device management app " + mMdmPackageName +
237               " on managed profile");
238 
239         try {
240             int status = mIpm.installExistingPackageAsUser(
241                 mMdmPackageName, mManagedProfileUserInfo.id);
242             switch (status) {
243               case PackageManager.INSTALL_SUCCEEDED:
244                   return;
245               case PackageManager.INSTALL_FAILED_USER_RESTRICTED:
246                   // Should not happen because we're not installing a restricted user
247                   error("Could not install mobile device management app on managed "
248                           + "profile because the user is restricted");
249               case PackageManager.INSTALL_FAILED_INVALID_URI:
250                   // Should not happen because we already checked
251                   error("Could not install mobile device management app on managed "
252                           + "profile because the package could not be found");
253               default:
254                   error("Could not install mobile device management app on managed "
255                           + "profile. Unknown status: " + status);
256             }
257         } catch (RemoteException neverThrown) {
258             // Never thrown, as we are making local calls.
259             ProvisionLogger.loge("This should not happen.", neverThrown);
260         }
261     }
262 
setMdmAsManagedProfileOwner()263     private void setMdmAsManagedProfileOwner() {
264 
265         ProvisionLogger.logd("Setting package " + mMdmPackageName + " as managed profile owner.");
266 
267         DevicePolicyManager dpm =
268                 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
269         if (!dpm.setProfileOwner(mActiveAdminComponentName, mMdmPackageName,
270                 mManagedProfileUserInfo.id)) {
271             ProvisionLogger.logw("Could not set profile owner.");
272             error("Could not set profile owner.");
273         }
274     }
275 
setMdmAsActiveAdmin()276     private void setMdmAsActiveAdmin() {
277 
278         ProvisionLogger.logd("Setting package " + mMdmPackageName + " as active admin.");
279 
280         DevicePolicyManager dpm =
281                 (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
282         dpm.setActiveAdmin(mActiveAdminComponentName, true /* refreshing*/,
283                 mManagedProfileUserInfo.id);
284     }
285 
286     /**
287      * Notify the mdm that provisioning has completed. When the mdm has received the intent, stop
288      * the service and notify the {@link ManagedProvisioningActivity} so that it can finish itself.
289      *
290      * @param deviceAdminComponent The component of the mdm that will be notified.
291      */
onProvisioningSuccess(ComponentName deviceAdminComponent)292     private void onProvisioningSuccess(ComponentName deviceAdminComponent) {
293         Settings.Secure.putIntForUser(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE,
294                 1 /* true- > setup complete */, mManagedProfileUserInfo.id);
295 
296         UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
297         UserHandle userHandle = userManager.getUserForSerialNumber(
298                 mManagedProfileUserInfo.serialNumber);
299 
300         Intent completeIntent = new Intent(ACTION_PROFILE_PROVISIONING_COMPLETE);
301         completeIntent.setComponent(mActiveAdminComponentName);
302         completeIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES |
303             Intent.FLAG_RECEIVER_FOREGROUND);
304         if (mAdminExtrasBundle != null) {
305             completeIntent.putExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE, mAdminExtrasBundle);
306         }
307 
308         // Use an ordered broadcast, so that we only finish when the mdm has received it.
309         // Avoids a lag in the transition between provisioning and the mdm.
310         BroadcastReceiver mdmReceivedSuccessReceiver = new BroadcastReceiver() {
311             @Override
312             public void onReceive(Context context, Intent intent) {
313                 ProvisionLogger.logd("ACTION_PROFILE_PROVISIONING_COMPLETE broadcast received by"
314                         + " mdm");
315                 Intent successIntent = new Intent(ACTION_PROVISIONING_SUCCESS);
316                 LocalBroadcastManager.getInstance(ManagedProvisioningService.this)
317                         .sendBroadcast(successIntent);
318                 stopSelf();
319             }
320 
321         };
322         sendOrderedBroadcastAsUser(completeIntent, userHandle, null,
323                 mdmReceivedSuccessReceiver, null, Activity.RESULT_OK, null, null);
324 
325         ProvisionLogger.logd("Provisioning complete broadcast has been sent to user "
326             + userHandle.getIdentifier());
327     }
328 
error(String logMessage)329     private void error(String logMessage) {
330         Intent intent = new Intent(ACTION_PROVISIONING_ERROR);
331         intent.putExtra(EXTRA_LOG_MESSAGE_KEY, logMessage);
332         LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
333         cleanup();
334         stopSelf();
335     }
336 
337     /**
338      * Performs cleanup of the device on failure.
339      */
cleanup()340     private void cleanup() {
341         // The only cleanup we need to do is remove the profile we created.
342         if (mManagedProfileUserInfo != null) {
343             ProvisionLogger.logd("Removing managed profile");
344             mUserManager.removeUser(mManagedProfileUserInfo.id);
345         }
346     }
347 
348     @Override
onBind(Intent intent)349     public IBinder onBind(Intent intent) {
350         return null;
351     }
352 
353     @Override
onDestroy()354     public void onDestroy() {
355         ProvisionLogger.logd("ManagedProvisioningService  ONDESTROY");
356     }
357 }
358