15005244f10442e75c1f48973fdddce5facf3f360Adrian Roos/*
25005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * Copyright (C) 2014 The Android Open Source Project
35005244f10442e75c1f48973fdddce5facf3f360Adrian Roos *
45005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * Licensed under the Apache License, Version 2.0 (the "License");
55005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * you may not use this file except in compliance with the License.
65005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * You may obtain a copy of the License at
75005244f10442e75c1f48973fdddce5facf3f360Adrian Roos *
85005244f10442e75c1f48973fdddce5facf3f360Adrian Roos *      http://www.apache.org/licenses/LICENSE-2.0
95005244f10442e75c1f48973fdddce5facf3f360Adrian Roos *
105005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * Unless required by applicable law or agreed to in writing, software
115005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * distributed under the License is distributed on an "AS IS" BASIS,
125005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * See the License for the specific language governing permissions and
145005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * limitations under the License
155005244f10442e75c1f48973fdddce5facf3f360Adrian Roos */
165005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
175005244f10442e75c1f48973fdddce5facf3f360Adrian Roospackage com.android.systemui;
185005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
195005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport com.android.systemui.statusbar.phone.SystemUIDialog;
205005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
215005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.app.ActivityManagerNative;
225005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.app.Dialog;
235005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.BroadcastReceiver;
245005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.ContentResolver;
255005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.Context;
265005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.DialogInterface;
275005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.Intent;
285005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.IntentFilter;
295005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.content.pm.UserInfo;
305005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.os.RemoteException;
315005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.os.UserHandle;
325005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.os.UserManager;
335005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.provider.Settings;
345005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.util.Log;
355005244f10442e75c1f48973fdddce5facf3f360Adrian Roosimport android.view.WindowManagerGlobal;
365005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
375005244f10442e75c1f48973fdddce5facf3f360Adrian Roos/**
385005244f10442e75c1f48973fdddce5facf3f360Adrian Roos * Manages notification when a guest session is resumed.
395005244f10442e75c1f48973fdddce5facf3f360Adrian Roos */
405005244f10442e75c1f48973fdddce5facf3f360Adrian Roospublic class GuestResumeSessionReceiver extends BroadcastReceiver {
415005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
425005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private static final String TAG = "GuestResumeSessionReceiver";
435005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
445005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private static final String SETTING_GUEST_HAS_LOGGED_IN = "systemui.guest_has_logged_in";
455005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
465005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private Dialog mNewSessionDialog;
475005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
485005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    public void register(Context context) {
495005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        IntentFilter f = new IntentFilter(Intent.ACTION_USER_SWITCHED);
505005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        context.registerReceiverAsUser(this, UserHandle.OWNER,
515005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                f, null /* permission */, null /* scheduler */);
525005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
535005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
545005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    @Override
555005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    public void onReceive(Context context, Intent intent) {
565005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        String action = intent.getAction();
575005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
585005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        if (Intent.ACTION_USER_SWITCHED.equals(action)) {
595005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            cancelDialog();
605005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
615005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, UserHandle.USER_NULL);
625005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (userId == UserHandle.USER_NULL) {
635005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                Log.e(TAG, intent + " sent to " + TAG + " without EXTRA_USER_HANDLE");
645005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                return;
655005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
665005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
675005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            UserInfo currentUser;
685005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            try {
695005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                currentUser = ActivityManagerNative.getDefault().getCurrentUser();
705005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            } catch (RemoteException e) {
715005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                return;
725005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
735005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (!currentUser.isGuest()) {
745005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                return;
755005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
765005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
775005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            ContentResolver cr = context.getContentResolver();
785005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            int notFirstLogin = Settings.System.getIntForUser(
795005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    cr, SETTING_GUEST_HAS_LOGGED_IN, 0, userId);
805005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (notFirstLogin != 0) {
815005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                mNewSessionDialog = new ResetSessionDialog(context, userId);
825005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                mNewSessionDialog.show();
835005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            } else {
845005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                Settings.System.putIntForUser(
855005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                        cr, SETTING_GUEST_HAS_LOGGED_IN, 1, userId);
865005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
875005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
885005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
895005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
905005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    /**
915005244f10442e75c1f48973fdddce5facf3f360Adrian Roos     * Wipes the guest session.
925005244f10442e75c1f48973fdddce5facf3f360Adrian Roos     *
935005244f10442e75c1f48973fdddce5facf3f360Adrian Roos     * The guest must be the current user and its id must be {@param userId}.
945005244f10442e75c1f48973fdddce5facf3f360Adrian Roos     */
955005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private static void wipeGuestSession(Context context, int userId) {
965005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
975005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        UserInfo currentUser;
985005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        try {
995005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            currentUser = ActivityManagerNative.getDefault().getCurrentUser();
1005005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        } catch (RemoteException e) {
1015005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            Log.e(TAG, "Couldn't wipe session because ActivityManager is dead");
1025005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            return;
1035005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
1045005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        if (currentUser.id != userId) {
1055005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            Log.w(TAG, "User requesting to start a new session (" + userId + ")"
1065005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    + " is not current user (" + currentUser.id + ")");
1075005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            return;
1085005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
1095005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        if (!currentUser.isGuest()) {
1105005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            Log.w(TAG, "User requesting to start a new session (" + userId + ")"
1115005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    + " is not a guest");
1125005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            return;
1135005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
1145005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1151df1473008c24487701c5bc15f39ed9f9697f421Amith Yamasani        boolean marked = userManager.markGuestForDeletion(currentUser.id);
1161df1473008c24487701c5bc15f39ed9f9697f421Amith Yamasani        if (!marked) {
1171df1473008c24487701c5bc15f39ed9f9697f421Amith Yamasani            Log.w(TAG, "Couldn't mark the guest for deletion for user " + userId);
1181df1473008c24487701c5bc15f39ed9f9697f421Amith Yamasani            return;
1191df1473008c24487701c5bc15f39ed9f9697f421Amith Yamasani        }
1205005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        UserInfo newGuest = userManager.createGuest(context, currentUser.name);
1215005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1225005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        try {
1235005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (newGuest == null) {
1245005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                Log.e(TAG, "Could not create new guest, switching back to owner");
1255005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                ActivityManagerNative.getDefault().switchUser(UserHandle.USER_OWNER);
1261df1473008c24487701c5bc15f39ed9f9697f421Amith Yamasani                userManager.removeUser(currentUser.id);
1275005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                WindowManagerGlobal.getWindowManagerService().lockNow(null /* options */);
1285005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                return;
1295005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
1305005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            ActivityManagerNative.getDefault().switchUser(newGuest.id);
1311df1473008c24487701c5bc15f39ed9f9697f421Amith Yamasani            userManager.removeUser(currentUser.id);
1325005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        } catch (RemoteException e) {
1335005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            Log.e(TAG, "Couldn't wipe session because ActivityManager or WindowManager is dead");
1345005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            return;
1355005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
1365005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
1375005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1385005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private void cancelDialog() {
1395005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        if (mNewSessionDialog != null && mNewSessionDialog.isShowing()) {
1405005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mNewSessionDialog.cancel();
1415005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mNewSessionDialog = null;
1425005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
1435005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
1445005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1455005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    private static class ResetSessionDialog extends SystemUIDialog implements
1465005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            DialogInterface.OnClickListener {
1475005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1485005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        private static final int BUTTON_WIPE = BUTTON_NEGATIVE;
1495005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        private static final int BUTTON_DONTWIPE = BUTTON_POSITIVE;
1505005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1515005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        private final int mUserId;
1525005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1535005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        public ResetSessionDialog(Context context, int userId) {
1545005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            super(context);
1555005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1565005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setTitle(context.getString(R.string.guest_wipe_session_title));
1575005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setMessage(context.getString(R.string.guest_wipe_session_message));
1585005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setCanceledOnTouchOutside(false);
1595005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1605005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(BUTTON_WIPE,
1615005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    context.getString(R.string.guest_wipe_session_wipe), this);
1625005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            setButton(BUTTON_DONTWIPE,
1635005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                    context.getString(R.string.guest_wipe_session_dontwipe), this);
1645005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1655005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            mUserId = userId;
1665005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
1675005244f10442e75c1f48973fdddce5facf3f360Adrian Roos
1685005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        @Override
1695005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        public void onClick(DialogInterface dialog, int which) {
1705005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            if (which == BUTTON_WIPE) {
1715005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                wipeGuestSession(getContext(), mUserId);
1725005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                dismiss();
1735005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            } else if (which == BUTTON_DONTWIPE) {
1745005244f10442e75c1f48973fdddce5facf3f360Adrian Roos                cancel();
1755005244f10442e75c1f48973fdddce5facf3f360Adrian Roos            }
1765005244f10442e75c1f48973fdddce5facf3f360Adrian Roos        }
1775005244f10442e75c1f48973fdddce5facf3f360Adrian Roos    }
1785005244f10442e75c1f48973fdddce5facf3f360Adrian Roos}
179