Loading core/java/android/app/supervision/ISupervisionManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -21,5 +21,5 @@ package android.app.supervision; * {@hide} */ interface ISupervisionManager { boolean isSupervisionEnabled(); boolean isSupervisionEnabledForUser(int userId); } core/java/android/app/supervision/SupervisionManager.java +3 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.app.supervision; import android.annotation.SystemService; import android.annotation.UserHandleAware; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.RemoteException; Loading Loading @@ -45,13 +46,12 @@ public class SupervisionManager { * * @hide */ @UserHandleAware public boolean isSupervisionEnabled() { try { return mService.isSupervisionEnabled(); return mService.isSupervisionEnabledForUser(mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } services/supervision/java/com/android/server/supervision/SupervisionManagerInternal.java 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.server.supervision; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.os.Bundle; /** * Local system service interface for {@link SupervisionService}. * * @hide Only for use within Android OS. */ public abstract class SupervisionManagerInternal { /** * Returns whether supervision is enabled for the specified user * * @param userId The user to retrieve the supervision state for * @return whether the user is supervised */ public abstract boolean isSupervisionEnabledForUser(@UserIdInt int userId); /** * Sets whether the supervision lock screen should be shown for the specified user * * @param userId The user set the superivision state for * @param enabled Whether or not the superivision lock screen needs to be shown * @param options Optional configuration parameters for the supervision lock screen */ public abstract void setSupervisionLockscreenEnabledForUser( @UserIdInt int userId, boolean enabled, @Nullable Bundle options); } services/supervision/java/com/android/server/supervision/SupervisionService.java +88 −7 Original line number Diff line number Diff line Loading @@ -18,14 +18,22 @@ package com.android.server.supervision; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.supervision.ISupervisionManager; import android.content.Context; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.UserManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -38,13 +46,25 @@ public class SupervisionService extends ISupervisionManager.Stub { private final Context mContext; // TODO(b/362756788): Does this need to be a LockGuard lock? private final Object mLockDoNoUseDirectly = new Object(); @GuardedBy("getLockObject()") private final SparseArray<SupervisionUserData> mUserData = new SparseArray<>(); private final UserManagerInternal mUserManagerInternal; public SupervisionService(Context context) { mContext = context.createAttributionContext("SupervisionService"); mContext = context.createAttributionContext(LOG_TAG); mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener()); } @Override public boolean isSupervisionEnabled() { return false; public boolean isSupervisionEnabledForUser(@UserIdInt int userId) { synchronized (getLockObject()) { return getUserDataLocked(userId).supervisionEnabled; } } @Override Loading @@ -60,11 +80,44 @@ public class SupervisionService extends ISupervisionManager.Stub { } @Override protected void dump( @NonNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args) { if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, fout)) return; protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter printWriter, @Nullable String[] args) { if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, printWriter)) return; try (var pw = new IndentingPrintWriter(printWriter, " ")) { pw.println("SupervisionService state:"); pw.increaseIndent(); var users = mUserManagerInternal.getUsers(false); synchronized (getLockObject()) { for (var user : users) { getUserDataLocked(user.id).dump(pw); pw.println(); } } } } private Object getLockObject() { return mLockDoNoUseDirectly; } @NonNull @GuardedBy("getLockObject()") SupervisionUserData getUserDataLocked(@UserIdInt int userId) { SupervisionUserData data = mUserData.get(userId); if (data == null) { // TODO(b/362790738): Do not create user data for nonexistent users. data = new SupervisionUserData(userId); mUserData.append(userId, data); } return data; } fout.println("Supervision enabled: " + isSupervisionEnabled()); void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled) { synchronized (getLockObject()) { getUserDataLocked(userId).supervisionEnabled = enabled; } } public static class Lifecycle extends SystemService { Loading @@ -77,7 +130,35 @@ public class SupervisionService extends ISupervisionManager.Stub { @Override public void onStart() { publishLocalService(SupervisionManagerInternal.class, mSupervisionService.mInternal); publishBinderService(Context.SUPERVISION_SERVICE, mSupervisionService); } } final SupervisionManagerInternal mInternal = new SupervisionManagerInternal() { public boolean isSupervisionEnabledForUser(@UserIdInt int userId) { synchronized (getLockObject()) { return getUserDataLocked(userId).supervisionEnabled; } } @Override public void setSupervisionLockscreenEnabledForUser( @UserIdInt int userId, boolean enabled, @Nullable Bundle options) { synchronized (getLockObject()) { SupervisionUserData data = getUserDataLocked(userId); data.supervisionLockScreenEnabled = enabled; data.supervisionLockScreenOptions = options; } } }; private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener { @Override public void onUserRemoved(UserInfo user) { synchronized (getLockObject()) { mUserData.remove(user.id); } } } } services/supervision/java/com/android/server/supervision/SupervisionServiceShellCommand.java +15 −17 Original line number Diff line number Diff line Loading @@ -17,8 +17,7 @@ package com.android.server.supervision; import android.os.ShellCommand; import java.io.PrintWriter; import android.os.UserHandle; public class SupervisionServiceShellCommand extends ShellCommand { private final SupervisionService mService; Loading @@ -32,30 +31,29 @@ public class SupervisionServiceShellCommand extends ShellCommand { if (cmd == null) { return handleDefaultCommands(null); } final PrintWriter pw = getOutPrintWriter(); switch (cmd) { case "help": return help(pw); case "is-enabled": return isEnabled(pw); case "enable": return setEnabled(true); case "disable": return setEnabled(false); default: return handleDefaultCommands(cmd); } } private int help(PrintWriter pw) { pw.println("Supervision service commands:"); pw.println(" help"); pw.println(" Prints this help text"); pw.println(" is-enabled"); pw.println(" Is supervision enabled"); return 0; } private int isEnabled(PrintWriter pw) { pw.println(mService.isSupervisionEnabled()); private int setEnabled(boolean enabled) { final var pw = getOutPrintWriter(); final var userId = UserHandle.parseUserArg(getNextArgRequired()); mService.setSupervisionEnabledForUser(userId, enabled); return 0; } @Override public void onHelp() { help(getOutPrintWriter()); final var pw = getOutPrintWriter(); pw.println("Supervision service (supervision) commands:"); pw.println(" help"); pw.println(" Prints this help text"); pw.println(" enable <USER_ID>"); pw.println(" Enables supervision for the given user."); pw.println(" disable <USER_ID>"); pw.println(" Disables supervision for the given user."); } } Loading
core/java/android/app/supervision/ISupervisionManager.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -21,5 +21,5 @@ package android.app.supervision; * {@hide} */ interface ISupervisionManager { boolean isSupervisionEnabled(); boolean isSupervisionEnabledForUser(int userId); }
core/java/android/app/supervision/SupervisionManager.java +3 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.app.supervision; import android.annotation.SystemService; import android.annotation.UserHandleAware; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.RemoteException; Loading Loading @@ -45,13 +46,12 @@ public class SupervisionManager { * * @hide */ @UserHandleAware public boolean isSupervisionEnabled() { try { return mService.isSupervisionEnabled(); return mService.isSupervisionEnabledForUser(mContext.getUserId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } }
services/supervision/java/com/android/server/supervision/SupervisionManagerInternal.java 0 → 100644 +46 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.server.supervision; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.os.Bundle; /** * Local system service interface for {@link SupervisionService}. * * @hide Only for use within Android OS. */ public abstract class SupervisionManagerInternal { /** * Returns whether supervision is enabled for the specified user * * @param userId The user to retrieve the supervision state for * @return whether the user is supervised */ public abstract boolean isSupervisionEnabledForUser(@UserIdInt int userId); /** * Sets whether the supervision lock screen should be shown for the specified user * * @param userId The user set the superivision state for * @param enabled Whether or not the superivision lock screen needs to be shown * @param options Optional configuration parameters for the supervision lock screen */ public abstract void setSupervisionLockscreenEnabledForUser( @UserIdInt int userId, boolean enabled, @Nullable Bundle options); }
services/supervision/java/com/android/server/supervision/SupervisionService.java +88 −7 Original line number Diff line number Diff line Loading @@ -18,14 +18,22 @@ package com.android.server.supervision; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.supervision.ISupervisionManager; import android.content.Context; import android.content.pm.UserInfo; import android.os.Bundle; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ShellCallback; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.DumpUtils; import com.android.internal.util.IndentingPrintWriter; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.pm.UserManagerInternal; import java.io.FileDescriptor; import java.io.PrintWriter; Loading @@ -38,13 +46,25 @@ public class SupervisionService extends ISupervisionManager.Stub { private final Context mContext; // TODO(b/362756788): Does this need to be a LockGuard lock? private final Object mLockDoNoUseDirectly = new Object(); @GuardedBy("getLockObject()") private final SparseArray<SupervisionUserData> mUserData = new SparseArray<>(); private final UserManagerInternal mUserManagerInternal; public SupervisionService(Context context) { mContext = context.createAttributionContext("SupervisionService"); mContext = context.createAttributionContext(LOG_TAG); mUserManagerInternal = LocalServices.getService(UserManagerInternal.class); mUserManagerInternal.addUserLifecycleListener(new UserLifecycleListener()); } @Override public boolean isSupervisionEnabled() { return false; public boolean isSupervisionEnabledForUser(@UserIdInt int userId) { synchronized (getLockObject()) { return getUserDataLocked(userId).supervisionEnabled; } } @Override Loading @@ -60,11 +80,44 @@ public class SupervisionService extends ISupervisionManager.Stub { } @Override protected void dump( @NonNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args) { if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, fout)) return; protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter printWriter, @Nullable String[] args) { if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, printWriter)) return; try (var pw = new IndentingPrintWriter(printWriter, " ")) { pw.println("SupervisionService state:"); pw.increaseIndent(); var users = mUserManagerInternal.getUsers(false); synchronized (getLockObject()) { for (var user : users) { getUserDataLocked(user.id).dump(pw); pw.println(); } } } } private Object getLockObject() { return mLockDoNoUseDirectly; } @NonNull @GuardedBy("getLockObject()") SupervisionUserData getUserDataLocked(@UserIdInt int userId) { SupervisionUserData data = mUserData.get(userId); if (data == null) { // TODO(b/362790738): Do not create user data for nonexistent users. data = new SupervisionUserData(userId); mUserData.append(userId, data); } return data; } fout.println("Supervision enabled: " + isSupervisionEnabled()); void setSupervisionEnabledForUser(@UserIdInt int userId, boolean enabled) { synchronized (getLockObject()) { getUserDataLocked(userId).supervisionEnabled = enabled; } } public static class Lifecycle extends SystemService { Loading @@ -77,7 +130,35 @@ public class SupervisionService extends ISupervisionManager.Stub { @Override public void onStart() { publishLocalService(SupervisionManagerInternal.class, mSupervisionService.mInternal); publishBinderService(Context.SUPERVISION_SERVICE, mSupervisionService); } } final SupervisionManagerInternal mInternal = new SupervisionManagerInternal() { public boolean isSupervisionEnabledForUser(@UserIdInt int userId) { synchronized (getLockObject()) { return getUserDataLocked(userId).supervisionEnabled; } } @Override public void setSupervisionLockscreenEnabledForUser( @UserIdInt int userId, boolean enabled, @Nullable Bundle options) { synchronized (getLockObject()) { SupervisionUserData data = getUserDataLocked(userId); data.supervisionLockScreenEnabled = enabled; data.supervisionLockScreenOptions = options; } } }; private final class UserLifecycleListener implements UserManagerInternal.UserLifecycleListener { @Override public void onUserRemoved(UserInfo user) { synchronized (getLockObject()) { mUserData.remove(user.id); } } } }
services/supervision/java/com/android/server/supervision/SupervisionServiceShellCommand.java +15 −17 Original line number Diff line number Diff line Loading @@ -17,8 +17,7 @@ package com.android.server.supervision; import android.os.ShellCommand; import java.io.PrintWriter; import android.os.UserHandle; public class SupervisionServiceShellCommand extends ShellCommand { private final SupervisionService mService; Loading @@ -32,30 +31,29 @@ public class SupervisionServiceShellCommand extends ShellCommand { if (cmd == null) { return handleDefaultCommands(null); } final PrintWriter pw = getOutPrintWriter(); switch (cmd) { case "help": return help(pw); case "is-enabled": return isEnabled(pw); case "enable": return setEnabled(true); case "disable": return setEnabled(false); default: return handleDefaultCommands(cmd); } } private int help(PrintWriter pw) { pw.println("Supervision service commands:"); pw.println(" help"); pw.println(" Prints this help text"); pw.println(" is-enabled"); pw.println(" Is supervision enabled"); return 0; } private int isEnabled(PrintWriter pw) { pw.println(mService.isSupervisionEnabled()); private int setEnabled(boolean enabled) { final var pw = getOutPrintWriter(); final var userId = UserHandle.parseUserArg(getNextArgRequired()); mService.setSupervisionEnabledForUser(userId, enabled); return 0; } @Override public void onHelp() { help(getOutPrintWriter()); final var pw = getOutPrintWriter(); pw.println("Supervision service (supervision) commands:"); pw.println(" help"); pw.println(" Prints this help text"); pw.println(" enable <USER_ID>"); pw.println(" Enables supervision for the given user."); pw.println(" disable <USER_ID>"); pw.println(" Disables supervision for the given user."); } }