Loading packages/SettingsLib/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,13 @@ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <application> <activity android:name=".users.CreateUserActivity" android:excludeFromRecents="true" android:exported="false" android:finishOnCloseSystemDialogs="true" android:launchMode="singleInstance" android:theme="@style/Theme.Transparent"/> </application> </manifest> packages/SettingsLib/res/layout/activity_create_new_user.xml 0 → 100644 +22 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (C) 2025 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:orientation="vertical"> </LinearLayout> No newline at end of file packages/SettingsLib/res/values/styles.xml +9 −0 Original line number Diff line number Diff line Loading @@ -116,4 +116,13 @@ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item> <item name="android:textSize">16dp</item> </style> <style name="Theme.Transparent" parent="@android:style/Theme.DeviceDefault.Settings"> <item name="android:windowActionBar">false</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> </style> </resources> packages/SettingsLib/src/com/android/settingslib/users/CreateUserActivity.java 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.users; import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.MotionEvent; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.R; public class CreateUserActivity extends Activity { private static final String TAG = "CreateUserActivity"; public static final String EXTRA_USER_NAME = "new_user_name"; public static final String EXTRA_IS_ADMIN = "is_admin"; public static final String EXTRA_USER_ICON_PATH = "user_icon_path"; private static final String DIALOG_STATE_KEY = "create_user_dialog_state"; private static final String EXTRA_CAN_CREATE_ADMIN = "can_create_admin"; private static final String EXTRA_FILE_AUTHORITY = "file_authority"; private CreateUserDialogController mCreateUserDialogController; @VisibleForTesting Dialog mSetupUserDialog; /** * Creates intent to start CreateUserActivity */ public static @NonNull Intent createIntentForStart(@NonNull Context context, boolean canCreateAdminUser, @NonNull String fileAuth) { Intent intent = new Intent(context, CreateUserActivity.class); intent.putExtra(EXTRA_CAN_CREATE_ADMIN, canCreateAdminUser); intent.putExtra(EXTRA_FILE_AUTHORITY, fileAuth); return intent; } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); mCreateUserDialogController = new CreateUserDialogController( intent.getStringExtra(EXTRA_FILE_AUTHORITY)); setContentView(R.layout.activity_create_new_user); if (savedInstanceState != null) { mCreateUserDialogController.onRestoreInstanceState(savedInstanceState); } mSetupUserDialog = createDialog(intent.getBooleanExtra(EXTRA_CAN_CREATE_ADMIN, false)); mSetupUserDialog.show(); } @Override protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); Bundle savedDialogState = savedInstanceState.getBundle(DIALOG_STATE_KEY); if (savedDialogState != null && mSetupUserDialog != null) { mSetupUserDialog.onRestoreInstanceState(savedDialogState); } } private Dialog createDialog(boolean canCreateAdminUser) { return mCreateUserDialogController.createDialog( this, this::startActivity, canCreateAdminUser, this::setSuccessResult, this::cancel ); } @Override public boolean onTouchEvent(@Nullable MotionEvent event) { onBackInvoked(); return super.onTouchEvent(event); } private void onBackInvoked() { if (mSetupUserDialog != null) { mSetupUserDialog.dismiss(); } setResult(RESULT_CANCELED); finish(); } @VisibleForTesting void setSuccessResult(String userName, Drawable userIcon, String path, Boolean isAdmin) { Intent intent = new Intent(this, CreateUserActivity.class); intent.putExtra(EXTRA_USER_NAME, userName); intent.putExtra(EXTRA_IS_ADMIN, isAdmin); intent.putExtra(EXTRA_USER_ICON_PATH, path); mSetupUserDialog.dismiss(); setResult(RESULT_OK, intent); finish(); } @VisibleForTesting void cancel() { mSetupUserDialog.dismiss(); setResult(RESULT_CANCELED); finish(); } @Override protected void onSaveInstanceState(@NonNull Bundle outState) { if (mSetupUserDialog != null && mSetupUserDialog.isShowing()) { outState.putBundle(DIALOG_STATE_KEY, mSetupUserDialog.onSaveInstanceState()); } mCreateUserDialogController.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { mCreateUserDialogController.onActivityResult(requestCode, resultCode, data); } private void startActivity(Intent intent, int requestCode) { startActivityForResult(intent, requestCode); mCreateUserDialogController.startingActivityForResult(); } } packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java +13 −5 Original line number Diff line number Diff line Loading @@ -242,7 +242,7 @@ public class CreateUserDialogController { .setMessage(messageResId) .setNegativeButtonText(R.string.cancel) .setPositiveButtonText(R.string.next); mCustomDialogHelper.requestFocusOnTitle(); focus(); break; case GRANT_ADMIN_DIALOG: mEditUserInfoView.setVisibility(View.GONE); Loading @@ -255,7 +255,7 @@ public class CreateUserDialogController { .setMessage(R.string.user_grant_admin_message) .setNegativeButtonText(R.string.back) .setPositiveButtonText(R.string.next); mCustomDialogHelper.requestFocusOnTitle(); focus(); if (mIsAdmin == null) { mCustomDialogHelper.setButtonEnabled(false); } Loading @@ -267,7 +267,7 @@ public class CreateUserDialogController { .setTitle(R.string.user_info_settings_title) .setNegativeButtonText(R.string.back) .setPositiveButtonText(R.string.done); mCustomDialogHelper.requestFocusOnTitle(); focus(); mEditUserInfoView.setVisibility(View.VISIBLE); mGrantAdminView.setVisibility(View.GONE); break; Loading @@ -282,7 +282,7 @@ public class CreateUserDialogController { mCustomDialogHelper.getDialog().dismiss(); break; case EXIT_DIALOG: mCustomDialogHelper.getDialog().dismiss(); finish(); break; default: if (mCurrentState < EXIT_DIALOG) { Loading Loading @@ -394,13 +394,21 @@ public class CreateUserDialogController { return mCustomDialogHelper != null && mCustomDialogHelper.getDialog() != null; } void focus() { mCustomDialogHelper.requestFocusOnTitle(); } /** * Runs callback and clears saved values after dialog is dismissed. */ public void finish() { if (mCurrentState == CREATE_USER_AND_CLOSE) { if (mSuccessCallback != null) { mSuccessCallback.onSuccess(mUserName, mNewUserIcon, Boolean.TRUE.equals(mIsAdmin)); if (mEditUserPhotoController != null && mCachedDrawablePath == null) { mCachedDrawablePath = mEditUserPhotoController.getCachedDrawablePath(); } mSuccessCallback.onSuccess(mUserName, mNewUserIcon, mCachedDrawablePath, Boolean.TRUE.equals(mIsAdmin)); } } else { if (mCancelCallback != null) { Loading Loading
packages/SettingsLib/AndroidManifest.xml +7 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,13 @@ <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" /> <application> <activity android:name=".users.CreateUserActivity" android:excludeFromRecents="true" android:exported="false" android:finishOnCloseSystemDialogs="true" android:launchMode="singleInstance" android:theme="@style/Theme.Transparent"/> </application> </manifest>
packages/SettingsLib/res/layout/activity_create_new_user.xml 0 → 100644 +22 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (C) 2025 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/transparent" android:orientation="vertical"> </LinearLayout> No newline at end of file
packages/SettingsLib/res/values/styles.xml +9 −0 Original line number Diff line number Diff line Loading @@ -116,4 +116,13 @@ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item> <item name="android:textSize">16dp</item> </style> <style name="Theme.Transparent" parent="@android:style/Theme.DeviceDefault.Settings"> <item name="android:windowActionBar">false</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> </style> </resources>
packages/SettingsLib/src/com/android/settingslib/users/CreateUserActivity.java 0 → 100644 +145 −0 Original line number Diff line number Diff line /* * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settingslib.users; import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.MotionEvent; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.settingslib.R; public class CreateUserActivity extends Activity { private static final String TAG = "CreateUserActivity"; public static final String EXTRA_USER_NAME = "new_user_name"; public static final String EXTRA_IS_ADMIN = "is_admin"; public static final String EXTRA_USER_ICON_PATH = "user_icon_path"; private static final String DIALOG_STATE_KEY = "create_user_dialog_state"; private static final String EXTRA_CAN_CREATE_ADMIN = "can_create_admin"; private static final String EXTRA_FILE_AUTHORITY = "file_authority"; private CreateUserDialogController mCreateUserDialogController; @VisibleForTesting Dialog mSetupUserDialog; /** * Creates intent to start CreateUserActivity */ public static @NonNull Intent createIntentForStart(@NonNull Context context, boolean canCreateAdminUser, @NonNull String fileAuth) { Intent intent = new Intent(context, CreateUserActivity.class); intent.putExtra(EXTRA_CAN_CREATE_ADMIN, canCreateAdminUser); intent.putExtra(EXTRA_FILE_AUTHORITY, fileAuth); return intent; } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Intent intent = getIntent(); mCreateUserDialogController = new CreateUserDialogController( intent.getStringExtra(EXTRA_FILE_AUTHORITY)); setContentView(R.layout.activity_create_new_user); if (savedInstanceState != null) { mCreateUserDialogController.onRestoreInstanceState(savedInstanceState); } mSetupUserDialog = createDialog(intent.getBooleanExtra(EXTRA_CAN_CREATE_ADMIN, false)); mSetupUserDialog.show(); } @Override protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); Bundle savedDialogState = savedInstanceState.getBundle(DIALOG_STATE_KEY); if (savedDialogState != null && mSetupUserDialog != null) { mSetupUserDialog.onRestoreInstanceState(savedDialogState); } } private Dialog createDialog(boolean canCreateAdminUser) { return mCreateUserDialogController.createDialog( this, this::startActivity, canCreateAdminUser, this::setSuccessResult, this::cancel ); } @Override public boolean onTouchEvent(@Nullable MotionEvent event) { onBackInvoked(); return super.onTouchEvent(event); } private void onBackInvoked() { if (mSetupUserDialog != null) { mSetupUserDialog.dismiss(); } setResult(RESULT_CANCELED); finish(); } @VisibleForTesting void setSuccessResult(String userName, Drawable userIcon, String path, Boolean isAdmin) { Intent intent = new Intent(this, CreateUserActivity.class); intent.putExtra(EXTRA_USER_NAME, userName); intent.putExtra(EXTRA_IS_ADMIN, isAdmin); intent.putExtra(EXTRA_USER_ICON_PATH, path); mSetupUserDialog.dismiss(); setResult(RESULT_OK, intent); finish(); } @VisibleForTesting void cancel() { mSetupUserDialog.dismiss(); setResult(RESULT_CANCELED); finish(); } @Override protected void onSaveInstanceState(@NonNull Bundle outState) { if (mSetupUserDialog != null && mSetupUserDialog.isShowing()) { outState.putBundle(DIALOG_STATE_KEY, mSetupUserDialog.onSaveInstanceState()); } mCreateUserDialogController.onSaveInstanceState(outState); super.onSaveInstanceState(outState); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { mCreateUserDialogController.onActivityResult(requestCode, resultCode, data); } private void startActivity(Intent intent, int requestCode) { startActivityForResult(intent, requestCode); mCreateUserDialogController.startingActivityForResult(); } }
packages/SettingsLib/src/com/android/settingslib/users/CreateUserDialogController.java +13 −5 Original line number Diff line number Diff line Loading @@ -242,7 +242,7 @@ public class CreateUserDialogController { .setMessage(messageResId) .setNegativeButtonText(R.string.cancel) .setPositiveButtonText(R.string.next); mCustomDialogHelper.requestFocusOnTitle(); focus(); break; case GRANT_ADMIN_DIALOG: mEditUserInfoView.setVisibility(View.GONE); Loading @@ -255,7 +255,7 @@ public class CreateUserDialogController { .setMessage(R.string.user_grant_admin_message) .setNegativeButtonText(R.string.back) .setPositiveButtonText(R.string.next); mCustomDialogHelper.requestFocusOnTitle(); focus(); if (mIsAdmin == null) { mCustomDialogHelper.setButtonEnabled(false); } Loading @@ -267,7 +267,7 @@ public class CreateUserDialogController { .setTitle(R.string.user_info_settings_title) .setNegativeButtonText(R.string.back) .setPositiveButtonText(R.string.done); mCustomDialogHelper.requestFocusOnTitle(); focus(); mEditUserInfoView.setVisibility(View.VISIBLE); mGrantAdminView.setVisibility(View.GONE); break; Loading @@ -282,7 +282,7 @@ public class CreateUserDialogController { mCustomDialogHelper.getDialog().dismiss(); break; case EXIT_DIALOG: mCustomDialogHelper.getDialog().dismiss(); finish(); break; default: if (mCurrentState < EXIT_DIALOG) { Loading Loading @@ -394,13 +394,21 @@ public class CreateUserDialogController { return mCustomDialogHelper != null && mCustomDialogHelper.getDialog() != null; } void focus() { mCustomDialogHelper.requestFocusOnTitle(); } /** * Runs callback and clears saved values after dialog is dismissed. */ public void finish() { if (mCurrentState == CREATE_USER_AND_CLOSE) { if (mSuccessCallback != null) { mSuccessCallback.onSuccess(mUserName, mNewUserIcon, Boolean.TRUE.equals(mIsAdmin)); if (mEditUserPhotoController != null && mCachedDrawablePath == null) { mCachedDrawablePath = mEditUserPhotoController.getCachedDrawablePath(); } mSuccessCallback.onSuccess(mUserName, mNewUserIcon, mCachedDrawablePath, Boolean.TRUE.equals(mIsAdmin)); } } else { if (mCancelCallback != null) { Loading