1 /*
2  * Copyright (C) 2021 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 package com.android.server;
17 
18 import android.annotation.Nullable;
19 import android.annotation.UserIdInt;
20 import android.content.ContentResolver;
21 import android.content.pm.PackageManager;
22 import android.content.pm.UserInfo;
23 import android.database.ContentObserver;
24 import android.os.Handler;
25 import android.os.Looper;
26 import android.os.UserHandle;
27 import android.os.UserManager;
28 import android.provider.Settings;
29 
30 import com.android.server.am.ActivityManagerService;
31 import com.android.server.pm.PackageManagerService;
32 import com.android.server.pm.UserManagerInternal;
33 import com.android.server.utils.Slogf;
34 import com.android.server.utils.TimingsTraceAndSlog;
35 
36 /**
37  * Class responsible for booting the device in the proper user on headless system user mode.
38  *
39  */
40 final class HsumBootUserInitializer {
41 
42     private static final String TAG = HsumBootUserInitializer.class.getSimpleName();
43 
44     private final UserManagerInternal mUmi;
45     private final ActivityManagerService mAms;
46     private final PackageManagerService mPms;
47     private final ContentResolver mContentResolver;
48 
49     private final ContentObserver mDeviceProvisionedObserver =
50             new ContentObserver(new Handler(Looper.getMainLooper())) {
51                 @Override
52                 public void onChange(boolean selfChange) {
53                     // Set USER_SETUP_COMPLETE for the (headless) system user only when the device
54                     // has been set up at least once.
55                     if (isDeviceProvisioned()) {
56                         Slogf.i(TAG, "Marking USER_SETUP_COMPLETE for system user");
57                         Settings.Secure.putInt(mContentResolver,
58                                 Settings.Secure.USER_SETUP_COMPLETE, 1);
59                         mContentResolver.unregisterContentObserver(mDeviceProvisionedObserver);
60                     }
61                 }
62             };
63 
64     /** Whether this device should always have a non-removable MainUser, including at first boot. */
65     private final boolean mShouldAlwaysHaveMainUser;
66 
67     /** Static factory method for creating a {@link HsumBootUserInitializer} instance. */
createInstance(ActivityManagerService am, PackageManagerService pms, ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser)68     public static @Nullable HsumBootUserInitializer createInstance(ActivityManagerService am,
69             PackageManagerService pms, ContentResolver contentResolver,
70             boolean shouldAlwaysHaveMainUser) {
71 
72         if (!UserManager.isHeadlessSystemUserMode()) {
73             return null;
74         }
75         return new HsumBootUserInitializer(
76                 LocalServices.getService(UserManagerInternal.class),
77                 am, pms, contentResolver,
78                 shouldAlwaysHaveMainUser);
79     }
80 
HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am, PackageManagerService pms, ContentResolver contentResolver, boolean shouldAlwaysHaveMainUser)81     private HsumBootUserInitializer(UserManagerInternal umi, ActivityManagerService am,
82             PackageManagerService pms, ContentResolver contentResolver,
83             boolean shouldAlwaysHaveMainUser) {
84         mUmi = umi;
85         mAms = am;
86         mPms = pms;
87         mContentResolver = contentResolver;
88         mShouldAlwaysHaveMainUser = shouldAlwaysHaveMainUser;
89     }
90 
91     /**
92      * Initialize this object, and create MainUser if needed.
93      *
94      * <p>Should be called before PHASE_SYSTEM_SERVICES_READY as services' setups may require
95      * MainUser, but probably after PHASE_LOCK_SETTINGS_READY since that may be needed for user
96      * creation.
97      */
init(TimingsTraceAndSlog t)98     public void init(TimingsTraceAndSlog t) {
99         Slogf.i(TAG, "init())");
100 
101         if (mShouldAlwaysHaveMainUser) {
102             t.traceBegin("createMainUserIfNeeded");
103             createMainUserIfNeeded();
104             t.traceEnd();
105         }
106     }
107 
createMainUserIfNeeded()108     private void createMainUserIfNeeded() {
109         final int mainUser = mUmi.getMainUserId();
110         if (mainUser != UserHandle.USER_NULL) {
111             Slogf.d(TAG, "Found existing MainUser, userId=%d", mainUser);
112             return;
113         }
114 
115         Slogf.d(TAG, "Creating a new MainUser");
116         try {
117             final UserInfo newInitialUser = mUmi.createUserEvenWhenDisallowed(
118                     /* name= */ null, // null will appear as "Owner" in on-demand localisation
119                     UserManager.USER_TYPE_FULL_SECONDARY,
120                     UserInfo.FLAG_ADMIN | UserInfo.FLAG_MAIN,
121                     /* disallowedPackages= */ null,
122                     /* token= */ null);
123             Slogf.i(TAG, "Successfully created MainUser, userId=%d", newInitialUser.id);
124         } catch (UserManager.CheckedUserOperationException e) {
125             Slogf.wtf(TAG, "Initial bootable MainUser creation failed", e);
126         }
127     }
128 
129     /**
130      * Put the device into the correct user state: unlock the system and switch to the boot user.
131      *
132      * <p>Should only call once PHASE_THIRD_PARTY_APPS_CAN_START is reached to ensure that
133      * privileged apps have had the chance to set the boot user, if applicable.
134      */
systemRunning(TimingsTraceAndSlog t)135     public void systemRunning(TimingsTraceAndSlog t) {
136         observeDeviceProvisioning();
137         unlockSystemUser(t);
138 
139         try {
140             t.traceBegin("getBootUser");
141             final int bootUser = mUmi.getBootUser(/* waitUntilSet= */ mPms
142                     .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, /* version= */0));
143             t.traceEnd();
144             t.traceBegin("switchToBootUser-" + bootUser);
145             switchToBootUser(bootUser);
146             t.traceEnd();
147         } catch (UserManager.CheckedUserOperationException e) {
148             Slogf.wtf(TAG, "Failed to switch to boot user since there isn't one.");
149         }
150     }
151 
observeDeviceProvisioning()152     private void observeDeviceProvisioning() {
153         if (isDeviceProvisioned()) {
154             return;
155         }
156 
157         mContentResolver.registerContentObserver(
158                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
159                 false,
160                 mDeviceProvisionedObserver
161         );
162     }
163 
isDeviceProvisioned()164     private boolean isDeviceProvisioned() {
165         try {
166             return Settings.Global.getInt(mContentResolver,
167                     Settings.Global.DEVICE_PROVISIONED) == 1;
168         } catch (Exception e) {
169             Slogf.wtf(TAG, "DEVICE_PROVISIONED setting not found.", e);
170             return false;
171         }
172     }
173 
174     // NOTE: Mostly copied from Automotive's InitialUserSetter
175     // TODO(b/266158156): Refactor how starting/unlocking works for the System.
unlockSystemUser(TimingsTraceAndSlog t)176     private void unlockSystemUser(TimingsTraceAndSlog t) {
177         Slogf.i(TAG, "Unlocking system user");
178         t.traceBegin("unlock-system-user");
179         try {
180             // This is for force changing state into RUNNING_LOCKED. Otherwise unlock does not
181             // update the state and USER_SYSTEM unlock happens twice.
182             t.traceBegin("am.startUser");
183             final boolean started = mAms.startUserInBackgroundWithListener(UserHandle.USER_SYSTEM,
184                             /* listener= */ null);
185             t.traceEnd();
186             if (!started) {
187                 Slogf.w(TAG, "could not restart system user in background; trying unlock instead");
188                 t.traceBegin("am.unlockUser");
189                 final boolean unlocked = mAms.unlockUser(UserHandle.USER_SYSTEM, /* token= */ null,
190                         /* secret= */ null, /* listener= */ null);
191                 t.traceEnd();
192                 if (!unlocked) {
193                     Slogf.w(TAG, "could not unlock system user either");
194                 }
195             }
196         } finally {
197             t.traceEnd();
198         }
199     }
200 
switchToBootUser(@serIdInt int bootUserId)201     private void switchToBootUser(@UserIdInt int bootUserId) {
202         Slogf.i(TAG, "Switching to boot user %d", bootUserId);
203         final boolean started = mAms.startUserInForegroundWithListener(bootUserId,
204                 /* unlockListener= */ null);
205         if (!started) {
206             Slogf.wtf(TAG, "Failed to start user %d in foreground", bootUserId);
207         }
208     }
209 }
210