Merge "Add controllers which determine top-level entry behavior into settings categories." into pi-car-dev
diff --git a/src/com/android/car/settings/accounts/AccountsEntryPreferenceController.java b/src/com/android/car/settings/accounts/AccountsEntryPreferenceController.java
new file mode 100644
index 0000000..2f69a89
--- /dev/null
+++ b/src/com/android/car/settings/accounts/AccountsEntryPreferenceController.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 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.car.settings.accounts;
+
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+
+import com.android.car.settings.common.NoSetupPreferenceController;
+
+/**
+ * Controller which determines if the top level entry into Account settings should be displayed
+ * based on the user status.
+ */
+public class AccountsEntryPreferenceController extends NoSetupPreferenceController {
+
+    private final CarUserManagerHelper mCarUserManagerHelper;
+
+    public AccountsEntryPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mCarUserManagerHelper = new CarUserManagerHelper(context);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mCarUserManagerHelper.canCurrentProcessModifyAccounts() ? AVAILABLE
+                : DISABLED_FOR_USER;
+    }
+}
diff --git a/src/com/android/car/settings/bluetooth/BluetoothEntryPreferenceController.java b/src/com/android/car/settings/bluetooth/BluetoothEntryPreferenceController.java
new file mode 100644
index 0000000..1e65db8
--- /dev/null
+++ b/src/com/android/car/settings/bluetooth/BluetoothEntryPreferenceController.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 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.car.settings.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+
+import com.android.car.settings.common.BasePreferenceController;
+
+/**
+ * Controller which determines if the top level entry into Bluetooth settings should be displayed
+ * based on device capabilities.
+ */
+public class BluetoothEntryPreferenceController extends BasePreferenceController {
+
+    public BluetoothEntryPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return (BluetoothAdapter.getDefaultAdapter() != null) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+}
diff --git a/src/com/android/car/settings/security/SecurityEntryPreferenceController.java b/src/com/android/car/settings/security/SecurityEntryPreferenceController.java
new file mode 100644
index 0000000..931d64f
--- /dev/null
+++ b/src/com/android/car/settings/security/SecurityEntryPreferenceController.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2018 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.car.settings.security;
+
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+
+import com.android.car.settings.common.NoSetupPreferenceController;
+
+/**
+ * Controller which determines if the top level entry into Security settings should be displayed
+ * based on the user status.
+ */
+public class SecurityEntryPreferenceController extends NoSetupPreferenceController {
+
+    private final CarUserManagerHelper mCarUserManagerHelper;
+
+    public SecurityEntryPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mCarUserManagerHelper = new CarUserManagerHelper(context);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return mCarUserManagerHelper.isCurrentProcessGuestUser() ? DISABLED_FOR_USER : AVAILABLE;
+    }
+}
diff --git a/src/com/android/car/settings/users/UsersEntryPreferenceController.java b/src/com/android/car/settings/users/UsersEntryPreferenceController.java
new file mode 100644
index 0000000..c6f9ca0
--- /dev/null
+++ b/src/com/android/car/settings/users/UsersEntryPreferenceController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.car.settings.users;
+
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.preference.Preference;
+
+import com.android.car.settings.common.Logger;
+import com.android.car.settings.common.NoSetupPreferenceController;
+
+import java.util.Objects;
+
+/**
+ * Controller which determines if the top level entry into User settings should direct to a list
+ * of all users or a user details page based on the current user's admin status.
+ */
+public class UsersEntryPreferenceController extends NoSetupPreferenceController {
+
+    private static final Logger LOG = new Logger(UsersEntryPreferenceController.class);
+
+    private final CarUserManagerHelper mCarUserManagerHelper;
+
+    public UsersEntryPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+        mCarUserManagerHelper = new CarUserManagerHelper(context);
+    }
+
+    @Override
+    public boolean handlePreferenceTreeClick(Preference preference) {
+        if (!Objects.equals(getPreferenceKey(), preference.getKey())) {
+            return false;
+        }
+        if (mCarUserManagerHelper.isCurrentProcessAdminUser()) {
+            // Admins can see a full list of users in Settings.
+            LOG.v("Creating UsersListFragment for admin user.");
+            preference.setFragment(UsersListFragment.class.getName());
+        } else {
+            // Non-admins can only manage themselves in Settings.
+            LOG.v("Creating UserDetailsFragment for non-admin.");
+            preference.setFragment(UserDetailsFragment.class.getName());
+            preference.getExtras().putInt(Intent.EXTRA_USER_ID,
+                    mCarUserManagerHelper.getCurrentProcessUserId());
+        }
+        // Don't handle so that the preference fragment gets launched.
+        return false;
+    }
+}
diff --git a/src/com/android/car/settings/wifi/WifiEntryPreferenceController.java b/src/com/android/car/settings/wifi/WifiEntryPreferenceController.java
new file mode 100644
index 0000000..3f5bdf8
--- /dev/null
+++ b/src/com/android/car/settings/wifi/WifiEntryPreferenceController.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 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.car.settings.wifi;
+
+import android.content.Context;
+
+import com.android.car.settings.common.BasePreferenceController;
+
+/**
+ * Controller which determines if the top level entry into Wi-Fi settings should be displayed
+ * based on device capabilities.
+ */
+public class WifiEntryPreferenceController extends BasePreferenceController {
+
+    public WifiEntryPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return WifiUtil.isWifiAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/accounts/AccountsEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/accounts/AccountsEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..86698ee
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/accounts/AccountsEntryPreferenceControllerTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 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.car.settings.accounts;
+
+import static com.android.car.settings.common.BasePreferenceController.AVAILABLE;
+import static com.android.car.settings.common.BasePreferenceController.DISABLED_FOR_USER;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.car.userlib.CarUserManagerHelper;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.testutils.ShadowCarUserManagerHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+/** Unit test for {@link AccountsEntryPreferenceController}. */
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowCarUserManagerHelper.class})
+public class AccountsEntryPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    @Mock
+    private CarUserManagerHelper mCarUserManagerHelper;
+    private AccountsEntryPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowCarUserManagerHelper.setMockInstance(mCarUserManagerHelper);
+
+        mController = new AccountsEntryPreferenceController(RuntimeEnvironment.application,
+                PREFERENCE_KEY);
+    }
+
+    @Test
+    public void getAvailabilityStatus_cannotModifyAccounts_disabledForUser() {
+        when(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
+    }
+
+    @Test
+    public void getAvailabilityStatus_canModifyAccounts_available() {
+        when(mCarUserManagerHelper.canCurrentProcessModifyAccounts()).thenReturn(true);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/bluetooth/BluetoothEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/bluetooth/BluetoothEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..b6be240
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/bluetooth/BluetoothEntryPreferenceControllerTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 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.car.settings.bluetooth;
+
+import static com.android.car.settings.common.BasePreferenceController.AVAILABLE;
+import static com.android.car.settings.common.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+
+import java.lang.reflect.Field;
+
+/** Unit test for {@link BluetoothEntryPreferenceController}. */
+@RunWith(CarSettingsRobolectricTestRunner.class)
+public class BluetoothEntryPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    private BluetoothEntryPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        mController = new BluetoothEntryPreferenceController(RuntimeEnvironment.application,
+                PREFERENCE_KEY);
+    }
+
+    @Test
+    public void getAvailabilityStatus_defaultAdapterAvailable_available() {
+        // Bluetooth adapter is always available in Robolectric.
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_defaultAdapterNull_unsupportedOnDevice()
+            throws NoSuchFieldException, IllegalAccessException {
+        // Since Robolectric doesn't allow setting the adapter availability, we null it here.
+        // See BluetoothAdapter.getDefaultAdapter Javadoc for API behavior.
+        ShadowApplication shadowApplication = ShadowApplication.getInstance();
+        Field defaultAdapterField = shadowApplication.getClass().getDeclaredField(
+                "bluetoothAdapter");
+        defaultAdapterField.setAccessible(true);
+        defaultAdapterField.set(shadowApplication, null);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/security/SecurityEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/security/SecurityEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..040570b
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/security/SecurityEntryPreferenceControllerTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2018 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.car.settings.security;
+
+import static com.android.car.settings.common.BasePreferenceController.AVAILABLE;
+import static com.android.car.settings.common.BasePreferenceController.DISABLED_FOR_USER;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.car.userlib.CarUserManagerHelper;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.testutils.ShadowCarUserManagerHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+/** Unit test for {@link SecurityEntryPreferenceController}. */
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowCarUserManagerHelper.class})
+public class SecurityEntryPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    @Mock
+    private CarUserManagerHelper mCarUserManagerHelper;
+    private SecurityEntryPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowCarUserManagerHelper.setMockInstance(mCarUserManagerHelper);
+
+        mController = new SecurityEntryPreferenceController(RuntimeEnvironment.application,
+                PREFERENCE_KEY);
+    }
+
+    @Test
+    public void getAvailabilityStatus_guestUser_disabledForUser() {
+        when(mCarUserManagerHelper.isCurrentProcessGuestUser()).thenReturn(true);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_FOR_USER);
+    }
+
+    @Test
+    public void getAvailabilityStatus_nonGuestUser_available() {
+        when(mCarUserManagerHelper.isCurrentProcessGuestUser()).thenReturn(false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/testutils/ShadowCarUserManagerHelper.java b/tests/robotests/src/com/android/car/settings/testutils/ShadowCarUserManagerHelper.java
index a08bf07..9361691 100644
--- a/tests/robotests/src/com/android/car/settings/testutils/ShadowCarUserManagerHelper.java
+++ b/tests/robotests/src/com/android/car/settings/testutils/ShadowCarUserManagerHelper.java
@@ -53,6 +53,11 @@
     }
 
     @Implementation
+    public int getCurrentProcessUserId() {
+        return sMockInstance.getCurrentProcessUserId();
+    }
+
+    @Implementation
     public boolean isCurrentProcessUser(UserInfo userInfo) {
         return sMockInstance.isCurrentProcessUser(userInfo);
     }
@@ -78,13 +83,13 @@
     }
 
     @Implementation
-    public boolean isCurrentProcessDemoUser() {
-        return sMockInstance.isCurrentProcessDemoUser();
+    public boolean isUserLimitReached() {
+        return sMockInstance.isUserLimitReached();
     }
 
     @Implementation
-    public boolean isUserLimitReached() {
-        return sMockInstance.isUserLimitReached();
+    public boolean canCurrentProcessModifyAccounts() {
+        return sMockInstance.canCurrentProcessModifyAccounts();
     }
 
     @Implementation
@@ -113,11 +118,21 @@
     }
 
     @Implementation
+    public boolean isCurrentProcessDemoUser() {
+        return sMockInstance.isCurrentProcessDemoUser();
+    }
+
+    @Implementation
     public boolean isCurrentProcessAdminUser() {
         return sMockInstance.isCurrentProcessAdminUser();
     }
 
     @Implementation
+    public boolean isCurrentProcessGuestUser() {
+        return sMockInstance.isCurrentProcessGuestUser();
+    }
+
+    @Implementation
     public boolean removeUser(UserInfo userInfo, String guestUserName) {
         return sMockInstance.removeUser(userInfo, guestUserName);
     }
diff --git a/tests/robotests/src/com/android/car/settings/users/UsersEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/users/UsersEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..7555da4
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/users/UsersEntryPreferenceControllerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 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.car.settings.users;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.car.userlib.CarUserManagerHelper;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.preference.Preference;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+import com.android.car.settings.testutils.ShadowCarUserManagerHelper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+/** Unit test for {@link UsersEntryPreferenceController}. */
+@RunWith(CarSettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowCarUserManagerHelper.class})
+public class UsersEntryPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    @Mock
+    private CarUserManagerHelper mCarUserManagerHelper;
+    private Context mContext;
+    private UsersEntryPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        ShadowCarUserManagerHelper.setMockInstance(mCarUserManagerHelper);
+
+        mContext = RuntimeEnvironment.application;
+        mController = new UsersEntryPreferenceController(mContext, PREFERENCE_KEY);
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_keyMismatch_doesNothing() {
+        Preference preference = new Preference(mContext);
+        preference.setKey(mController.getPreferenceKey() + " wrong key");
+
+        assertThat(mController.handlePreferenceTreeClick(preference)).isFalse();
+        assertThat(preference.getFragment()).isNull();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_adminUser_returnsFalse() {
+        when(mCarUserManagerHelper.isCurrentProcessAdminUser()).thenReturn(true);
+        Preference preference = new Preference(mContext);
+        preference.setKey(mController.getPreferenceKey());
+
+        assertThat(mController.handlePreferenceTreeClick(preference)).isFalse();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_adminUser_setsUsersListFragment() {
+        when(mCarUserManagerHelper.isCurrentProcessAdminUser()).thenReturn(true);
+        Preference preference = new Preference(mContext);
+        preference.setKey(mController.getPreferenceKey());
+
+        mController.handlePreferenceTreeClick(preference);
+
+        assertThat(preference.getFragment()).isEqualTo(UsersListFragment.class.getName());
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_nonAdminUser_returnsFalse() {
+        when(mCarUserManagerHelper.isCurrentProcessAdminUser()).thenReturn(false);
+        Preference preference = new Preference(mContext);
+        preference.setKey(mController.getPreferenceKey());
+
+        assertThat(mController.handlePreferenceTreeClick(preference)).isFalse();
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_nonAdminUser_setsUserDetailsFragment() {
+        when(mCarUserManagerHelper.isCurrentProcessAdminUser()).thenReturn(false);
+        Preference preference = new Preference(mContext);
+        preference.setKey(mController.getPreferenceKey());
+
+        mController.handlePreferenceTreeClick(preference);
+
+        assertThat(preference.getFragment()).isEqualTo(UserDetailsFragment.class.getName());
+    }
+
+    @Test
+    public void handlePreferenceTreeClick_nonAdminUser_setsExtraUserId() {
+        int userId = 1234;
+        when(mCarUserManagerHelper.getCurrentProcessUserId()).thenReturn(userId);
+        when(mCarUserManagerHelper.isCurrentProcessAdminUser()).thenReturn(false);
+        Preference preference = new Preference(mContext);
+        preference.setKey(mController.getPreferenceKey());
+
+        mController.handlePreferenceTreeClick(preference);
+
+        assertThat(preference.getExtras()).isNotNull();
+        assertThat(preference.getExtras().getInt(Intent.EXTRA_USER_ID)).isEqualTo(userId);
+    }
+}
diff --git a/tests/robotests/src/com/android/car/settings/wifi/WifiEntryPreferenceControllerTest.java b/tests/robotests/src/com/android/car/settings/wifi/WifiEntryPreferenceControllerTest.java
new file mode 100644
index 0000000..8bfea03
--- /dev/null
+++ b/tests/robotests/src/com/android/car/settings/wifi/WifiEntryPreferenceControllerTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2018 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.car.settings.wifi;
+
+import static com.android.car.settings.common.BasePreferenceController.AVAILABLE;
+import static com.android.car.settings.common.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import com.android.car.settings.CarSettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowPackageManager;
+
+/** Unit test for {@link WifiEntryPreferenceController}. */
+@RunWith(CarSettingsRobolectricTestRunner.class)
+public class WifiEntryPreferenceControllerTest {
+
+    private static final String PREFERENCE_KEY = "preference_key";
+
+    private ShadowPackageManager mShadowPackageManager;
+    private WifiEntryPreferenceController mController;
+
+    @Before
+    public void setUp() {
+        Context context = RuntimeEnvironment.application;
+        mShadowPackageManager = Shadows.shadowOf(context.getPackageManager());
+        mController = new WifiEntryPreferenceController(context, PREFERENCE_KEY);
+    }
+
+    @Test
+    public void getAvailabilityStatus_wifiAvailable_available() {
+        mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_WIFI, /* supported= */ true);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+    }
+
+    @Test
+    public void getAvailabilityStatus_wifiNotAvailable_unsupportedOnDevice() {
+        mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_WIFI, /* supported= */ false);
+
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+    }
+}