1 /* 2 * Copyright (C) 2018 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.car.settings.profiles; 18 19 import android.app.ActivityManager; 20 import android.car.user.CarUserManager; 21 import android.car.user.UserCreationResult; 22 import android.car.user.UserStartRequest; 23 import android.car.user.UserStopRequest; 24 import android.car.util.concurrent.AsyncFuture; 25 import android.content.Context; 26 import android.content.pm.UserInfo; 27 import android.os.AsyncTask; 28 import android.os.UserHandle; 29 import android.os.UserManager; 30 31 import com.android.car.internal.user.UserHelper; 32 import com.android.car.settings.common.Logger; 33 34 import java.util.concurrent.ExecutionException; 35 36 /** 37 * Task to add a new profile to the device 38 */ 39 public class AddNewProfileTask extends AsyncTask<String, Void, UserInfo> { 40 private static final Logger LOG = new Logger(AddNewProfileTask.class); 41 42 private final Context mContext; 43 private final CarUserManager mCarUserManager; 44 private final AddNewProfileListener mAddNewProfileListener; 45 private final UserManager mUserManager; 46 AddNewProfileTask(Context context, CarUserManager carUserManager, AddNewProfileListener addNewProfileListener)47 public AddNewProfileTask(Context context, CarUserManager carUserManager, 48 AddNewProfileListener addNewProfileListener) { 49 mContext = context; 50 mCarUserManager = carUserManager; 51 mAddNewProfileListener = addNewProfileListener; 52 mUserManager = context.getSystemService(UserManager.class); 53 } 54 55 @Override doInBackground(String... profileNames)56 protected UserInfo doInBackground(String... profileNames) { 57 AsyncFuture<UserCreationResult> future = mCarUserManager.createUser(profileNames[0], 58 /* flags= */ 0); 59 try { 60 UserCreationResult result = future.get(); 61 if (result.isSuccess()) { 62 UserInfo user = mUserManager.getUserInfo(result.getUser().getIdentifier()); 63 if (user != null) { 64 UserHelper.setDefaultNonAdminRestrictions(mContext, user.getUserHandle(), 65 /* enable= */ true); 66 UserHelper.assignDefaultIcon(mContext, user.getUserHandle()); 67 } else { 68 LOG.wtf("Inconsistent state: successful future with null profile - " 69 + result.toString()); 70 } 71 return user; 72 } 73 } catch (InterruptedException | ExecutionException e) { 74 if (e instanceof InterruptedException) { 75 Thread.currentThread().interrupt(); 76 } 77 LOG.e("Error creating new profile: ", e); 78 } 79 return null; 80 } 81 82 @Override onPreExecute()83 protected void onPreExecute() { } 84 85 @Override onPostExecute(UserInfo user)86 protected void onPostExecute(UserInfo user) { 87 if (user != null) { 88 mAddNewProfileListener.onProfileAddedSuccess(); 89 UserHandle currentUser = mContext.getUser(); 90 91 if (currentUser.getIdentifier() == ActivityManager.getCurrentUser()) { 92 mCarUserManager.switchUser(user.id); 93 } else { 94 // For passengers we need to call stop and start 95 try { 96 mCarUserManager.stopUser( 97 new UserStopRequest.Builder(currentUser).setForce().build(), 98 mContext.getMainExecutor(), 99 result -> { 100 LOG.i("Stop user result: " + result.toString()); 101 if (result.isSuccess()) { 102 startUser(user); 103 } 104 }); 105 } catch (Exception e) { 106 LOG.e("Exception stopping user " + currentUser, e); 107 } 108 } 109 } else { 110 mAddNewProfileListener.onProfileAddedFailure(); 111 } 112 } 113 startUser(UserInfo user)114 private void startUser(UserInfo user) { 115 int displayId = mContext.getDisplayId(); 116 117 try { 118 mCarUserManager.startUser( 119 new UserStartRequest.Builder(user.getUserHandle()) 120 .setDisplayId(displayId) 121 .build(), 122 Runnable::run, 123 result -> LOG.i("Start user result: " + result.toString())); 124 } catch (Exception e) { 125 LOG.e("Exception starting user " + user.id, e); 126 } 127 } 128 129 /** 130 * Interface for getting notified when AddNewProfileTask has been completed. 131 */ 132 public interface AddNewProfileListener { 133 /** 134 * Invoked in AddNewProfileTask.onPostExecute after the profile has been created 135 * successfully. 136 */ onProfileAddedSuccess()137 void onProfileAddedSuccess(); 138 139 /** 140 * Invoked in AddNewProfileTask.onPostExecute if new profile creation failed. 141 */ onProfileAddedFailure()142 void onProfileAddedFailure(); 143 } 144 } 145