1 /*
2  * Copyright (C) 2014 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.android.tv.settings.users;
18 
19 import android.app.ActivityManager;
20 import android.app.Service;
21 import android.app.UserSwitchObserver;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.SharedPreferences;
27 import android.content.pm.PackageManager;
28 import android.os.IBinder;
29 import android.os.RemoteException;
30 import android.os.UserHandle;
31 import android.os.UserManager;
32 import android.util.Log;
33 
34 public class UserSwitchListenerService extends Service {
35 
36     private static final boolean DEBUG = false;
37     private static final String TAG = "RestrictedProfile";
38 
39     private static final String RESTRICTED_PROFILE_LAUNCHER_ENTRY_ACTIVITY =
40             "com.android.tv.settings.users.RestrictedProfileActivityLauncherEntry";
41     private static final String SHARED_PREFERENCES_NAME = "RestrictedProfileSharedPreferences";
42     private static final String
43             ON_BOOT_USER_ID_PREFERENCE = "UserSwitchOnBootBroadcastReceiver.userId";
44 
45     private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
46         @Override
47         public void onUserSwitchComplete(int newUserId) {
48             if (DEBUG) {
49                 Log.d(TAG, "user has been foregrounded: " + newUserId);
50             }
51             setBootUser(UserSwitchListenerService.this, newUserId);
52         }
53     };
54 
55     public static class BootReceiver extends BroadcastReceiver {
56         @Override
onReceive(final Context context, Intent intent)57         public void onReceive(final Context context, Intent intent) {
58             int bootUserId = getBootUser(context);
59             if (DEBUG) {
60                 Log.d(TAG, "boot completed, user is " + UserHandle.myUserId()
61                         + " boot user id: " + bootUserId);
62             }
63             if (UserManager.get(context).isSystemUser()) {
64                 if (UserHandle.myUserId() != bootUserId) {
65                     switchUserNow(bootUserId);
66                 }
67             }
68             onUserCreatedOrDeleted(context);
69         }
70     }
71 
72     /** The UserSwitchListenerService is only ever needed when there is a restricted profile. */
hasRestrictedProfile(Context context)73     private static boolean hasRestrictedProfile(Context context) {
74         return new RestrictedProfileModel(context).getUser() != null;
75     }
76 
77     /**
78      * Enable or disable the restricted profile launcher entry activity as well as the
79      * {@link UserSwitchListenerService} depending on whether there is a restricted profile.
80      */
onUserCreatedOrDeleted(final Context context)81     public static void onUserCreatedOrDeleted(final Context context) {
82         final boolean restrictedProfile = hasRestrictedProfile(context);
83         if (DEBUG) {
84             Log.d(TAG, "updating restricted profile : " + restrictedProfile);
85         }
86 
87         context.getPackageManager().setComponentEnabledSetting(new ComponentName(context,
88                         RESTRICTED_PROFILE_LAUNCHER_ENTRY_ACTIVITY), restrictedProfile
89                         ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
90                         : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
91                 PackageManager.DONT_KILL_APP);
92 
93         if (restrictedProfile) {
94             context.startServiceAsUser(new Intent(context, UserSwitchListenerService.class),
95                     UserHandle.SYSTEM);
96         } else {
97             context.stopServiceAsUser(new Intent(context, UserSwitchListenerService.class),
98                     UserHandle.SYSTEM);
99         }
100     }
101 
setBootUser(Context context, int userId)102     static void setBootUser(Context context, int userId) {
103         SharedPreferences.Editor editor = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
104                 Context.MODE_PRIVATE).edit();
105         editor.putInt(ON_BOOT_USER_ID_PREFERENCE, userId);
106         editor.apply();
107     }
108 
getBootUser(Context context)109     static int getBootUser(Context context) {
110         SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME,
111                 Context.MODE_PRIVATE);
112         return prefs.getInt(ON_BOOT_USER_ID_PREFERENCE, UserHandle.USER_SYSTEM);
113     }
114 
switchUserNow(int userId)115     private static void switchUserNow(int userId) {
116         try {
117             ActivityManager.getService().switchUser(userId);
118         } catch (RemoteException re) {
119             Log.e(TAG, "Caught exception while switching user! ", re);
120         }
121     }
122 
123     @Override
onCreate()124     public void onCreate() {
125         super.onCreate();
126         try {
127             ActivityManager.getService().registerUserSwitchObserver(
128                     mUserSwitchObserver,
129                     UserSwitchListenerService.class.getName());
130         } catch (RemoteException e) {
131             Log.e(TAG, "Caught exception while registering UserSwitchObserver", e);
132         }
133     }
134 
135     @Override
onDestroy()136     public void onDestroy() {
137         try {
138             ActivityManager.getService().unregisterUserSwitchObserver(mUserSwitchObserver);
139         } catch (RemoteException e) {
140             // Not much we can do here
141         }
142         super.onDestroy();
143     }
144 
145     @Override
onStartCommand(Intent intent, int flags, int startId)146     public int onStartCommand(Intent intent, int flags, int startId) {
147         if (!hasRestrictedProfile(this)) {
148             stopSelf();
149             Log.w(TAG, "no restricted profiles found! Immediately finishing "
150                     + UserSwitchListenerService.class.getSimpleName());
151         }
152         return START_STICKY;
153     }
154 
155     @Override
onBind(Intent intent)156     public IBinder onBind(Intent intent) {
157         return null;
158     }
159 }
160