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
17package com.android.managedprovisioning;
18
19import static android.app.admin.DeviceAdminReceiver.ACTION_PROFILE_PROVISIONING_COMPLETE;
20import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE;
21import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME;
22import static android.Manifest.permission.BIND_DEVICE_ADMIN;
23
24import android.app.Activity;
25import android.app.ActivityManagerNative;
26import android.app.IActivityManager;
27import android.app.Service;
28import android.app.admin.DevicePolicyManager;
29import android.content.BroadcastReceiver;
30import android.content.ComponentName;
31import android.content.Context;
32import android.content.Intent;
33import android.content.IntentFilter;
34import android.content.pm.ActivityInfo;
35import android.content.pm.IPackageManager;
36import android.content.pm.PackageInfo;
37import android.content.pm.PackageManager;
38import android.content.pm.PackageManager.NameNotFoundException;
39import android.content.pm.UserInfo;
40import android.os.AsyncTask;
41import android.os.Parcelable;
42import android.os.PersistableBundle;
43import android.os.IBinder;
44import android.os.Process;
45import android.os.RemoteException;
46import android.os.ServiceManager;
47import android.os.UserHandle;
48import android.os.UserManager;
49import android.provider.MediaStore;
50import android.provider.Settings;
51import android.support.v4.content.LocalBroadcastManager;
52import android.text.TextUtils;
53
54import com.android.managedprovisioning.CrossProfileIntentFiltersHelper;
55import 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 */
63public 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
88        protected Void doInBackground(Intent ... intents) {
89            initialize(intents[0]);
90            startManagedProfileProvisioning();
91            return null;
92        }
93    }
94
95    @Override
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
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
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     */
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     */
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     */
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
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     */
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
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
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
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     */
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
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     */
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
349    public IBinder onBind(Intent intent) {
350        return null;
351    }
352
353    @Override
354    public void onDestroy() {
355        ProvisionLogger.logd("ManagedProvisioningService  ONDESTROY");
356    }
357}
358