Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9dd2ad6e authored by Amith Yamasani's avatar Amith Yamasani Committed by Android (Google) Code Review
Browse files

Merge "Fix deadlock during user state transitions" into nyc-dev

parents 43b5d980 98c0556f
Loading
Loading
Loading
Loading
+52 −25
Original line number Diff line number Diff line
@@ -434,21 +434,47 @@ final class UserController {
                stoppingIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                stoppingIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
                stoppingIntent.putExtra(Intent.EXTRA_SHUTDOWN_USERSPACE_ONLY, true);
                final Intent shutdownIntent = new Intent(Intent.ACTION_SHUTDOWN);
                // This is the result receiver for the final shutdown broadcast.
                final IIntentReceiver shutdownReceiver = new IIntentReceiver.Stub() {
                // This is the result receiver for the initial stopping broadcast.
                final IIntentReceiver stoppingReceiver = new IIntentReceiver.Stub() {
                    @Override
                    public void performReceive(Intent intent, int resultCode, String data,
                            Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                        finishUserStop(uss);
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                finishUserStopping(userId, uss);
                            }
                        });
                    }
                };
                // This is the result receiver for the initial stopping broadcast.
                final IIntentReceiver stoppingReceiver = new IIntentReceiver.Stub() {
                // Kick things off.
                mService.broadcastIntentLocked(null, null, stoppingIntent,
                        null, stoppingReceiver, 0, null, null,
                        new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
                        null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

    void finishUserStopping(final int userId, final UserState uss) {
        // On to the next.
        final Intent shutdownIntent = new Intent(Intent.ACTION_SHUTDOWN);
        // This is the result receiver for the final shutdown broadcast.
        final IIntentReceiver shutdownReceiver = new IIntentReceiver.Stub() {
            @Override
            public void performReceive(Intent intent, int resultCode, String data,
                    Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
                        // On to the next.
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        finishUserStopped(uss);
                    }
                });
            }
        };

        synchronized (mService) {
            if (uss.state != UserState.STATE_STOPPING) {
                // Whoops, we are being started back up.  Abort, abort!
@@ -456,27 +482,21 @@ final class UserController {
            }
            uss.setState(UserState.STATE_SHUTDOWN);
        }

        mService.mBatteryStatsService.noteEvent(
                BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
                Integer.toString(userId), userId);
        mService.mSystemServiceManager.stopUser(userId);

        synchronized (mService) {
            mService.broadcastIntentLocked(null, null, shutdownIntent,
                                null, shutdownReceiver, 0, null, null, null, AppOpsManager.OP_NONE,
                    null, shutdownReceiver, 0, null, null, null,
                    AppOpsManager.OP_NONE,
                    null, true, false, MY_PID, SYSTEM_UID, userId);
        }
                };
                // Kick things off.
                mService.broadcastIntentLocked(null, null, stoppingIntent,
                        null, stoppingReceiver, 0, null, null,
                        new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
                        null, true, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    }

    void finishUserStop(UserState uss) {
    void finishUserStopped(UserState uss) {
        final int userId = uss.mHandle.getIdentifier();
        boolean stopped;
        ArrayList<IStopUserCallback> callbacks;
@@ -765,10 +785,17 @@ final class UserController {
                        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                        mService.broadcastIntentLocked(null, null, intent, null,
                                new IIntentReceiver.Stub() {
                                    @Override
                                    public void performReceive(Intent intent, int resultCode,
                                            String data, Bundle extras, boolean ordered,
                                            boolean sticky, int sendingUser) {
                                        onUserInitialized(uss, foreground, oldUserId, userId);
                                        mHandler.post(new Runnable() {
                                            @Override
                                            public void run() {
                                                onUserInitialized(uss, foreground,
                                                        oldUserId, userId);
                                            }
                                        });
                                    }
                                }, 0, null, null, null, AppOpsManager.OP_NONE,
                                null, true, false, MY_PID, SYSTEM_UID, userId);