1 /*
2  * Copyright (C) 2020 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.google.android.car.kitchensink.users;
18 
19 import android.annotation.NonNull;
20 import android.annotation.UserIdInt;
21 import android.app.ActivityManager;
22 import android.app.admin.DevicePolicyManager;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.pm.UserInfo;
26 import android.graphics.Bitmap;
27 import android.os.UserHandle;
28 import android.os.UserManager;
29 import android.util.AttributeSet;
30 import android.util.Log;
31 import android.widget.EditText;
32 import android.widget.LinearLayout;
33 import android.widget.TextView;
34 
35 import com.android.car.admin.ui.UserAvatarView;
36 import com.android.internal.util.UserIcons;
37 
38 import com.google.android.car.kitchensink.R;
39 
40 /**
41  * Custom {@link android.view.View} that shows an Android user info.
42  */
43 public final class UserInfoView extends LinearLayout {
44 
45     private static final String TAG = UserInfoView.class.getSimpleName();
46 
47     private UserAvatarView mUserAvatarView;
48     private EditText mUserIdEditText;
49     private EditText mUserNameEditText;
50     private EditText mUserTypeEditText;
51     private EditText mUserFlagsEditText;
52     private EditText mUserStatusEditText;
53     private TextView mManagedTextView;
54 
UserInfoView(Context context, AttributeSet attrs)55     public UserInfoView(Context context, AttributeSet attrs) {
56         super(context, attrs);
57 
58         inflate(context, R.layout.user_info_view, this);
59         mUserAvatarView = findViewById(R.id.user_avatar);
60         mUserIdEditText = findViewById(R.id.user_id);
61         mUserNameEditText = findViewById(R.id.user_name);
62         mUserTypeEditText = findViewById(R.id.user_type);
63         mUserFlagsEditText = findViewById(R.id.user_flags);
64         mUserStatusEditText = findViewById(R.id.user_status);
65         mManagedTextView = findViewById(R.id.managed);
66     }
67 
68     /**
69      * Initializes the widget with the given user.
70      */
update(@onNull UserInfo user)71     public void update(@NonNull UserInfo user) {
72         Log.v(TAG, "initializing with " + user.toFullString());
73 
74         setUserIcon(user.id);
75         mUserIdEditText.setText(String.valueOf(user.id));
76         mUserNameEditText.setText(user.name);
77         mUserTypeEditText.setText(user.userType);
78         mUserFlagsEditText.setText(UserInfo.flagsToString(user.flags));
79         mUserStatusEditText.setText(getStatus(user));
80         setManagedStatus(user.id);
81     }
82 
getStatus(@onNull UserInfo user)83     private String getStatus(@NonNull UserInfo user) {
84         ActivityManager am = (ActivityManager) getContext()
85                 .getSystemService(Context.ACTIVITY_SERVICE);
86         int currentUserId = ActivityManager.getCurrentUser();
87         boolean current = user.id == currentUserId;
88         boolean running = am.isUserRunning(user.id);
89         boolean visible = isUserVisible(user.id);
90         String s = new StringBuilder()
91                 .append(user.partial ? " (partial)" : "")
92                 .append(running ? " (running)" : "")
93                 .append(current ? " (current)" : "")
94                 .append(visible ? " (visible)" : "")
95                 .toString();
96         return s;
97     }
98 
isUserVisible(@serIdInt int userId)99     private boolean isUserVisible(@UserIdInt int userId) {
100         UserHandle user = UserHandle.of(userId);
101         Context context = mContext.createContextAsUser(user, /* flags= */ 0);
102         boolean visible = context.getSystemService(UserManager.class).isUserVisible();
103         Log.v(TAG, "isUserVisible(" + userId + "): " + visible);
104         return visible;
105     }
106 
setUserIcon(@serIdInt int userId)107     private void setUserIcon(@UserIdInt int userId) {
108         UserManager um = UserManager.get(getContext());
109         Bitmap icon = um.getUserIcon(userId);
110         if (icon == null) {
111             Log.v(TAG, "No icon for user " + userId); // Happens on system user
112             icon = UserIcons.convertToBitmap(
113                     UserIcons.getDefaultUserIcon(getResources(), userId, /* light= */ false));
114         }
115         mUserAvatarView.setAvatarWithBadge(icon, userId);
116     }
117 
setManagedStatus(@serIdInt int userId)118     private void setManagedStatus(@UserIdInt int userId) {
119         // Check managed status
120         DevicePolicyManager dpm = getContext().getSystemService(DevicePolicyManager.class);
121         if (dpm == null) return;
122 
123         UserHandle deviceOwner = dpm.getDeviceOwnerUser();
124         Log.v(TAG, "Device owner is " + deviceOwner);
125 
126         if (deviceOwner != null && deviceOwner.getIdentifier() == userId) {
127             setManagedText("DeviceOwner");
128             return;
129         }
130 
131         ComponentName profileOwner = dpm.getProfileOwnerAsUser(userId);
132         if (profileOwner != null) {
133             Log.v(TAG, "User " + userId + " has profile owner: " + profileOwner);
134             setManagedText("ProfileOwner");
135             return;
136         }
137         mManagedTextView.setVisibility(GONE);
138     }
139 
setManagedText(@onNull CharSequence text)140     private void setManagedText(@NonNull CharSequence text) {
141         mManagedTextView.setText(text);
142         mManagedTextView.setVisibility(VISIBLE);
143     }
144 }
145