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

Commit 4f93c58b authored by Jim Miller's avatar Jim Miller
Browse files

Add account locked notification when users are encrypted

Fixes bug 26407543

Change-Id: Ic66669cd5f75b5fa41449e33133439752cef112b
parent 8af734b8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -39,4 +39,5 @@ interface ILockSettings {
    void registerStrongAuthTracker(in IStrongAuthTracker tracker);
    void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
    void requireStrongAuth(int strongAuthReason, int userId);
    void systemReady();
}
+8 −0
Original line number Diff line number Diff line
@@ -4190,4 +4190,12 @@
    <string name="new_sms_notification_title">You have new messages</string>
    <!-- Notification content shown when new SMS/MMS is received while the device is locked [CHAR LIMIT=NONE] -->
    <string name="new_sms_notification_content">Open SMS app to view</string>

    <!-- Notification title shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
    <string name="user_encrypted_title">Device encrypted</string>
    <!-- Notification message shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
    <string name="user_encrypted_message">Some functions might not be available</string>
    <!-- Notification detail shown when user profile is credential encrypted and requires the user to unlock before some features are usable [CHAR LIMIT=30] -->
    <string name="user_encrypted_detail">Touch to continue</string>

</resources>
+6 −0
Original line number Diff line number Diff line
@@ -2505,4 +2505,10 @@
  <java-symbol type="string" name="new_sms_notification_content" />

  <java-symbol type="bool" name="config_strongAuthRequiredOnBoot" />

  <!-- Encryption notification while accounts are locked by credential encryption -->
  <java-symbol type="string" name="user_encrypted_title" />
  <java-symbol type="string" name="user_encrypted_message" />
  <java-symbol type="string" name="user_encrypted_detail" />

</resources>
+119 −7
Original line number Diff line number Diff line
@@ -17,11 +17,12 @@
package com.android.server;

import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
import android.app.trust.IStrongAuthTracker;
import android.app.trust.ITrustManager;
import android.app.trust.TrustManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
@@ -30,6 +31,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;

import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.content.Context.USER_SERVICE;
import static android.Manifest.permission.READ_CONTACTS;
@@ -40,7 +43,6 @@ import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -70,19 +72,27 @@ import java.util.List;
 * @hide
 */
public class LockSettingsService extends ILockSettings.Stub {

    private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;

    private static final String TAG = "LockSettingsService";
    private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
    private static final Intent ACTION_NULL; // hack to ensure notification shows the bouncer
    private static final int FBE_ENCRYPTED_NOTIFICATION = 0;
    private static final boolean DEBUG = false;

    private final Context mContext;

    private final LockSettingsStorage mStorage;
    private final LockSettingsStrongAuth mStrongAuth;

    private LockPatternUtils mLockPatternUtils;
    private boolean mFirstCallToVold;
    private IGateKeeperService mGateKeeperService;
    private NotificationManager mNotificationManager;
    private UserManager mUserManager;

    static {
        // Just launch the home screen, which happens anyway
        ACTION_NULL = new Intent(Intent.ACTION_MAIN);
        ACTION_NULL.addCategory(Intent.CATEGORY_HOME);
    }

    private interface CredentialUtil {
        void setCredential(String credential, String savedCredential, int userId)
@@ -91,6 +101,42 @@ public class LockSettingsService extends ILockSettings.Stub {
        String adjustForKeystore(String credential);
    }

    // This class manages life cycle events for encrypted users on File Based Encryption (FBE)
    // devices. The most basic of these is to show/hide notifications about missing features until
    // the user unlocks the account and credential-encrypted storage is available.
    public static final class Lifecycle extends SystemService {
        private LockSettingsService mLockSettingsService;

        public Lifecycle(Context context) {
            super(context);
        }

        @Override
        public void onStart() {
            mLockSettingsService = new LockSettingsService(getContext());
            publishBinderService("lock_settings", mLockSettingsService);
        }

        @Override
        public void onBootPhase(int phase) {
            if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                mLockSettingsService.maybeShowEncryptionNotification(UserHandle.ALL);
            } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
                // TODO
            }
        }

        @Override
        public void onUnlockUser(int userHandle) {
            mLockSettingsService.onUnlockUser(userHandle);
        }

        @Override
        public void onCleanupUser(int userHandle) {
            mLockSettingsService.onCleanupUser(userHandle);
        }
    }

    public LockSettingsService(Context context) {
        mContext = context;
        mStrongAuth = new LockSettingsStrongAuth(context);
@@ -117,6 +163,71 @@ public class LockSettingsService extends ILockSettings.Stub {
                }
            }
        });
        mNotificationManager = (NotificationManager)
                mContext.getSystemService(Context.NOTIFICATION_SERVICE);
        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    }

    /**
     * If the account is credential-encrypted, show notification requesting the user to unlock
     * the device.
     */
    private void maybeShowEncryptionNotification(UserHandle userHandle) {
        if (UserHandle.ALL.equals(userHandle)) {
            final List<UserInfo> users = mUserManager.getUsers();
            for (int i = 0; i < users.size(); i++) {
                UserHandle user = users.get(i).getUserHandle();
                if (!mUserManager.isUserUnlocked(user)) {
                    showEncryptionNotification(user);
                }
            }
        } else if (!mUserManager.isUserUnlocked(userHandle)){
            showEncryptionNotification(userHandle);
        }
    }

    private void showEncryptionNotification(UserHandle user) {
        if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
        Resources r = mContext.getResources();
        CharSequence title = r.getText(
                com.android.internal.R.string.user_encrypted_title);
        CharSequence message = r.getText(
                com.android.internal.R.string.user_encrypted_message);
        CharSequence detail = r.getText(
                com.android.internal.R.string.user_encrypted_detail);

        PendingIntent intent = PendingIntent.getBroadcast(mContext, 0, ACTION_NULL,
                PendingIntent.FLAG_UPDATE_CURRENT);

        Notification notification = new Notification.Builder(mContext)
                .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning)
                .setWhen(0)
                .setOngoing(true)
                .setTicker(title)
                .setDefaults(0)  // please be quiet
                .setPriority(Notification.PRIORITY_MAX)
                .setColor(mContext.getColor(
                        com.android.internal.R.color.system_notification_accent_color))
                .setContentTitle(title)
                .setContentText(message)
                .setContentInfo(detail)
                .setVisibility(Notification.VISIBILITY_PUBLIC)
                .setContentIntent(intent)
                .build();
        mNotificationManager.notifyAsUser(null, FBE_ENCRYPTED_NOTIFICATION, notification, user);
    }

    public void hideEncryptionNotification(UserHandle userHandle) {
        if (DEBUG) Slog.v(TAG, "hide encryption notification, user: "+ userHandle.getIdentifier());
        mNotificationManager.cancelAsUser(null, FBE_ENCRYPTED_NOTIFICATION, userHandle);
    }

    public void onCleanupUser(int userId) {
        hideEncryptionNotification(new UserHandle(userId));
    }

    public void onUnlockUser(int userHandle) {
        hideEncryptionNotification(new UserHandle(userHandle));
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -144,6 +255,7 @@ public class LockSettingsService extends ILockSettings.Stub {
        }
    };

    @Override // binder interface
    public void systemReady() {
        migrateOldData();
        try {
+7 −3
Original line number Diff line number Diff line
@@ -68,6 +68,7 @@ import com.android.server.hdmi.HdmiControlService;
import com.android.server.input.InputManagerService;
import com.android.server.job.JobSchedulerService;
import com.android.server.lights.LightsService;
import com.android.internal.widget.ILockSettings;
import com.android.server.media.MediaRouterService;
import com.android.server.media.MediaSessionService;
import com.android.server.media.MediaResourceMonitorService;
@@ -143,6 +144,8 @@ public final class SystemServer {
            "com.android.server.ethernet.EthernetService";
    private static final String JOB_SCHEDULER_SERVICE_CLASS =
            "com.android.server.job.JobSchedulerService";
    private static final String LOCK_SETTINGS_SERVICE_CLASS =
            "com.android.server.LockSettingsService$Lifecycle";
    private static final String MOUNT_SERVICE_CLASS =
            "com.android.server.MountService$Lifecycle";
    private static final String SEARCH_MANAGER_SERVICE_CLASS =
@@ -607,7 +610,7 @@ public final class SystemServer {
        LocationManagerService location = null;
        CountryDetectorService countryDetector = null;
        TextServicesManagerService tsms = null;
        LockSettingsService lockSettings = null;
        ILockSettings lockSettings = null;
        AssetAtlasService atlas = null;
        MediaRouterService mediaRouter = null;

@@ -680,8 +683,9 @@ public final class SystemServer {
            if (!disableNonCoreServices) {
                traceBeginAndSlog("StartLockSettingsService");
                try {
                    lockSettings = new LockSettingsService(context);
                    ServiceManager.addService("lock_settings", lockSettings);
                    mSystemServiceManager.startService(LOCK_SETTINGS_SERVICE_CLASS);
                    lockSettings = ILockSettings.Stub.asInterface(
                            ServiceManager.getService("lock_settings"));
                } catch (Throwable e) {
                    reportWtf("starting LockSettingsService service", e);
                }