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

Commit 33f9a9c2 authored by Kenny Guy's avatar Kenny Guy
Browse files

Allow widget hosts to see widgets from locked profiles.

Avoid launchers removing widgets by handling case
where a widget host is in an unlocked parent user and
widget providers are in a locked managed profile.
For this case allow launcher to see the widgets from
non-crypto aware widget providers.
Mask out widgets from locked profiles.
Fix issue with widgets not being masked when adding
new widgets when user is locked / quiet or package
is suspended.

Bug: 26721345
Bug: 27037962
Change-Id: I60b5bd934c1547110e374ab4eefbee6aade37dc6
parent 0f900c02
Loading
Loading
Loading
Loading
+60 −19
Original line number Original line Diff line number Diff line
@@ -159,7 +159,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                reloadWidgetsMaskedStateForUser(userId);
                reloadWidgetsMaskedStateForUser(userId);
            } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
            } else if (Intent.ACTION_MANAGED_PROFILE_AVAILABILITY_CHANGED.equals(action)) {
                synchronized (mLock) {
                synchronized (mLock) {
                    reloadWidgetQuietModeMaskedStateLocked(userId);
                    reloadWidgetProfileUnavailableMaskedStateLocked(userId);
                }
                }
            } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
            } else if (Intent.ACTION_PACKAGES_SUSPENDED.equals(action)) {
                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
@@ -432,7 +432,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku


    /**
    /**
     * Reload all widgets' masked state for the given user and its associated profiles, including
     * Reload all widgets' masked state for the given user and its associated profiles, including
     * due to quiet mode and package suspension.
     * due to user not being available and package suspension.
     */
     */
    private void reloadWidgetsMaskedStateForUser(int userId) {
    private void reloadWidgetsMaskedStateForUser(int userId) {
        if (!mUserManager.isUserUnlocked(userId)) return;
        if (!mUserManager.isUserUnlocked(userId)) return;
@@ -442,7 +442,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            if (profiles != null) {
            if (profiles != null) {
                for (int i = 0; i < profiles.size(); i++) {
                for (int i = 0; i < profiles.size(); i++) {
                    UserInfo user  = profiles.get(i);
                    UserInfo user  = profiles.get(i);
                    reloadWidgetQuietModeMaskedStateLocked(user.id);
                    reloadWidgetProfileUnavailableMaskedStateLocked(user.id);
                    reloadWidgetPackageSuspensionMaskedStateLocked(user.id);
                    reloadWidgetPackageSuspensionMaskedStateLocked(user.id);
                }
                }
            }
            }
@@ -450,17 +450,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    }
    }


    /**
    /**
     * Mask/unmask widgets in the given profile, depending on the quiet state of the profile.
     * Mask/unmask widgets in the given profile, depending on the quiet state
     * or locked state of the profile.
     */
     */
    private void reloadWidgetQuietModeMaskedStateLocked(int profileId) {
    private void reloadWidgetProfileUnavailableMaskedStateLocked(int profileId) {
        if (!mUserManager.isUserUnlocked(profileId)) return;
        final long identity = Binder.clearCallingIdentity();
        final long identity = Binder.clearCallingIdentity();
        try {
        try {
            UserInfo user  = mUserManager.getUserInfo(profileId);
            if (!isProfileWithUnlockedParent(profileId)) {
            if (!user.isManagedProfile()) {
                return;
                return;
            }
            }
            boolean shouldMask = user.isQuietModeEnabled();
            UserInfo user  = mUserManager.getUserInfo(profileId);
            boolean shouldMask = user.isQuietModeEnabled() ||
                    !mUserManager.isUserUnlocked(user.getUserHandle());
            final int N = mProviders.size();
            final int N = mProviders.size();
            for (int i = 0; i < N; i++) {
            for (int i = 0; i < N; i++) {
                Provider provider = mProviders.get(i);
                Provider provider = mProviders.get(i);
@@ -468,7 +469,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                if (providerUserId != profileId) {
                if (providerUserId != profileId) {
                    continue;
                    continue;
                }
                }
                if (provider.setMaskedByQuietProfileLocked(shouldMask)) {
                if (provider.setMaskedByProfileUnavailabledLocked(shouldMask)) {
                    if (provider.isMaskedLocked()) {
                    if (provider.isMaskedLocked()) {
                        maskWidgetsViewsLocked(provider);
                        maskWidgetsViewsLocked(provider);
                    } else {
                    } else {
@@ -537,8 +538,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        }
        }
    }
    }


    private void maskWidgetsViewsLocked(Provider provider) {
    private Bitmap createMaskedWidgetBitmap(Provider provider) {
        Bitmap iconBitmap = null;
        final long identity = Binder.clearCallingIdentity();
        try {
        try {
            // Load the unbadged application icon and pass it to the widget to appear on
            // Load the unbadged application icon and pass it to the widget to appear on
            // the masked view.
            // the masked view.
@@ -548,11 +549,20 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            PackageManager pm = userContext.getPackageManager();
            PackageManager pm = userContext.getPackageManager();
            Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
            Drawable icon = pm.getApplicationInfo(providerPackage, 0).loadUnbadgedIcon(pm);
            // Create a bitmap of the icon which is what the widget's remoteview requires.
            // Create a bitmap of the icon which is what the widget's remoteview requires.
            iconBitmap = mIconUtilities.createIconBitmap(icon);
            return mIconUtilities.createIconBitmap(icon);
        } catch (NameNotFoundException e) {
        } catch (NameNotFoundException e) {
            Slog.e(TAG, "Fail to get application icon", e);
            Slog.e(TAG, "Fail to get application icon", e);
            // Provider package removed, no need to mask its views as its state will be
            // Provider package removed, no need to mask its views as its state will be
            // purged very soon.
            // purged very soon.
            return null;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    private void maskWidgetsViewsLocked(Provider provider) {
        Bitmap iconBitmap = createMaskedWidgetBitmap(provider);
        if (iconBitmap == null) {
            return;
            return;
        }
        }


@@ -2320,7 +2330,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
                final PackageManager pm = mContext.getPackageManager();
                final PackageManager pm = mContext.getPackageManager();
                final int userId = UserHandle.getUserId(providerId.uid);
                final int userId = UserHandle.getUserId(providerId.uid);
                final ApplicationInfo app = pm.getApplicationInfoAsUser(activityInfo.packageName,
                final ApplicationInfo app = pm.getApplicationInfoAsUser(activityInfo.packageName,
                        PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
                        0, userId);
                resources = pm.getResourcesForApplication(app);
                resources = pm.getResourcesForApplication(app);
            } finally {
            } finally {
                Binder.restoreCallingIdentity(identity);
                Binder.restoreCallingIdentity(identity);
@@ -2423,9 +2433,16 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            int flags = PackageManager.GET_META_DATA;
            int flags = PackageManager.GET_META_DATA;


            // We really need packages to be around and parsed to know if they
            // We really need packages to be around and parsed to know if they
            // provide widgets, and we only load widgets after user is unlocked.
            // provide widgets.
            flags |= PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
            flags |= PackageManager.MATCH_DEBUG_TRIAGED_MISSING;


            // Widget hosts that are non-crypto aware may be hosting widgets
            // from a profile that is still locked, so let them see those
            // widgets.
            if (isProfileWithUnlockedParent(userId)) {
                flags |= PackageManager.MATCH_ENCRYPTION_AWARE_AND_UNAWARE;
            }

            // Widgets referencing shared libraries need to have their
            // Widgets referencing shared libraries need to have their
            // dependencies loaded.
            // dependencies loaded.
            flags |= PackageManager.GET_SHARED_LIBRARY_FILES;
            flags |= PackageManager.GET_SHARED_LIBRARY_FILES;
@@ -2443,6 +2460,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    private void onUserUnlocked(int userId) {
    private void onUserUnlocked(int userId) {
        synchronized (mLock) {
        synchronized (mLock) {
            ensureGroupStateLoadedLocked(userId);
            ensureGroupStateLoadedLocked(userId);
            reloadWidgetsMaskedStateForUser(userId);


            final int N = mProviders.size();
            final int N = mProviders.size();
            for (int i = 0; i < N; i++) {
            for (int i = 0; i < N; i++) {
@@ -2580,6 +2598,17 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
            mWidgetPackages.put(userId, packages = new ArraySet<String>());
            mWidgetPackages.put(userId, packages = new ArraySet<String>());
        }
        }
        packages.add(widget.provider.info.provider.getPackageName());
        packages.add(widget.provider.info.provider.getPackageName());

        // If we are adding a widget it might be for a provider that
        // is currently masked, if so mask the widget.
        if (widget.provider.isMaskedLocked()) {
            Bitmap bitmap = createMaskedWidgetBitmap(widget.provider);
            if (bitmap != null) {
                widget.replaceWithMaskedViewsLocked(mContext, bitmap);
            }
        } else {
            widget.clearMaskedViewsLocked();
        }
    }
    }


    /**
    /**
@@ -3277,6 +3306,18 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        }
        }
    }
    }


    private boolean isProfileWithUnlockedParent(int userId) {
        UserInfo userInfo = mUserManager.getUserInfo(userId);
        if (userInfo != null && userInfo.isManagedProfile()) {
            UserInfo parentInfo = mUserManager.getProfileParent(userId);
            if (parentInfo != null
                    && mUserManager.isUserUnlocked(parentInfo.getUserHandle())) {
                return true;
            }
        }
        return false;
    }

    private final class CallbackHandler extends Handler {
    private final class CallbackHandler extends Handler {
        public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1;
        public static final int MSG_NOTIFY_UPDATE_APP_WIDGET = 1;
        public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2;
        public static final int MSG_NOTIFY_PROVIDER_CHANGED = 2;
@@ -3554,7 +3595,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        PendingIntent broadcast;
        PendingIntent broadcast;
        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it
        boolean zombie; // if we're in safe mode, don't prune this just because nobody references it


        boolean maskedByQuietProfile;
        boolean maskedByProfileUnavailable;
        boolean maskedBySuspendedPackage;
        boolean maskedBySuspendedPackage;


        int tag = TAG_UNDEFINED; // for use while saving state (the index)
        int tag = TAG_UNDEFINED; // for use while saving state (the index)
@@ -3587,9 +3628,9 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        }
        }


        // returns true if the provider's masked state is changed as a result
        // returns true if the provider's masked state is changed as a result
        public boolean setMaskedByQuietProfileLocked(boolean masked) {
        public boolean setMaskedByProfileUnavailabledLocked(boolean masked) {
            boolean oldMaskedState = isMaskedLocked();
            boolean oldMaskedState = isMaskedLocked();
            maskedByQuietProfile = masked;
            maskedByProfileUnavailable = masked;
            return isMaskedLocked() != oldMaskedState;
            return isMaskedLocked() != oldMaskedState;
        }
        }


@@ -3601,7 +3642,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        }
        }


        public boolean isMaskedLocked() {
        public boolean isMaskedLocked() {
            return maskedByQuietProfile || maskedBySuspendedPackage;
            return maskedByProfileUnavailable || maskedBySuspendedPackage;
        }
        }
    }
    }