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

Commit 4f8a9d98 authored by Ruslan Tkhakokhov's avatar Ruslan Tkhakokhov
Browse files

Try to reapply live wallpaper component once it's installed

See go/br-fr-live-wallpaper for context

Bug: 30205325
Test: 1. Set live wallpaper (from pre-installed / from a 3p app Muzei)
      2. Run Backup Now
      3. Wipe the device
      4. Restore (regular/deferred)
      5. Verify the same live wallpaper is set
Change-Id: Iacdb4e4b4bd895740f0a7f72f075a24fae1ae368
parent be3b2304
Loading
Loading
Loading
Loading
+76 −17
Original line number Diff line number Diff line
@@ -36,10 +36,12 @@ import android.os.FileUtils;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.util.Xml;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.content.PackageMonitor;

import libcore.io.IoUtils;

@@ -261,22 +263,7 @@ public class WallpaperBackupAgent extends BackupAgent {

            // And reset to the wallpaper service we should be using
            ComponentName wpService = parseWallpaperComponent(infoStage, "wp");
            if (servicePackageExists(wpService)) {
                Slog.i(TAG, "Using wallpaper service " + wpService);
                mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM);
                if (!lockImageStage.exists()) {
                    // We have a live wallpaper and no static lock image,
                    // allow live wallpaper to show "through" on lock screen.
                    mWm.clear(FLAG_LOCK);
                }
            } else {
                // If we've restored a live wallpaper, but the component doesn't exist,
                // we should log it as an error so we can easily identify the problem
                // in reports from users
                if (wpService != null) {
                    Slog.e(TAG, "Wallpaper service " + wpService + " isn't available.");
                }
            }
            updateWallpaperComponent(wpService, !lockImageStage.exists());
        } catch (Exception e) {
            Slog.e(TAG, "Unable to restore wallpaper: " + e.getMessage());
        } finally {
@@ -293,6 +280,28 @@ public class WallpaperBackupAgent extends BackupAgent {
        }
    }

    @VisibleForTesting
    void updateWallpaperComponent(ComponentName wpService, boolean applyToLock) throws IOException {
        if (servicePackageExists(wpService)) {
            Slog.i(TAG, "Using wallpaper service " + wpService);
            mWm.setWallpaperComponent(wpService, UserHandle.USER_SYSTEM);
            if (applyToLock) {
                // We have a live wallpaper and no static lock image,
                // allow live wallpaper to show "through" on lock screen.
                mWm.clear(FLAG_LOCK);
            }
        } else {
            // If we've restored a live wallpaper, but the component doesn't exist,
            // we should log it as an error so we can easily identify the problem
            // in reports from users
            if (wpService != null) {
                applyComponentAtInstall(wpService, applyToLock);
                Slog.w(TAG, "Wallpaper service " + wpService + " isn't available. "
                        + " Will try to apply later");
            }
        }
    }

    private void restoreFromStage(File stage, File info, String hintTag, int which)
            throws IOException {
        if (stage.exists()) {
@@ -372,7 +381,8 @@ public class WallpaperBackupAgent extends BackupAgent {
        return (value == null) ? defValue : Integer.parseInt(value);
    }

    private boolean servicePackageExists(ComponentName comp) {
    @VisibleForTesting
    boolean servicePackageExists(ComponentName comp) {
        try {
            if (comp != null) {
                final IPackageManager pm = AppGlobals.getPackageManager();
@@ -401,4 +411,53 @@ public class WallpaperBackupAgent extends BackupAgent {
            throws IOException {
        // Intentionally blank
    }

    private void applyComponentAtInstall(ComponentName componentName, boolean applyToLock) {
        PackageMonitor packageMonitor = getWallpaperPackageMonitor(componentName, applyToLock);
        packageMonitor.register(getBaseContext(), null, UserHandle.ALL, true);
    }

    @VisibleForTesting
    PackageMonitor getWallpaperPackageMonitor(ComponentName componentName, boolean applyToLock) {
        return new PackageMonitor() {
            @Override
            public void onPackageAdded(String packageName, int uid) {
                if (!isDeviceInRestore()) {
                    // We don't want to reapply the wallpaper outside a restore.
                    unregister();
                    return;
                }

                if (componentName.getPackageName().equals(packageName)) {
                    Slog.d(TAG, "Applying component " + componentName);
                    mWm.setWallpaperComponent(componentName);
                    if (applyToLock) {
                        try {
                            mWm.clear(FLAG_LOCK);
                        } catch (IOException e) {
                            Slog.w(TAG, "Failed to apply live wallpaper to lock screen: " + e);
                        }
                    }
                    // We're only expecting to restore the wallpaper component once.
                    unregister();
                }
            }
        };
    }

    @VisibleForTesting
    boolean isDeviceInRestore() {
        try {
            boolean isInSetup = Settings.Secure.getInt(getBaseContext().getContentResolver(),
                    Settings.Secure.USER_SETUP_COMPLETE) == 0;
            boolean isInDeferredSetup = Settings.Secure.getInt(getBaseContext()
                            .getContentResolver(),
                    Settings.Secure.USER_SETUP_PERSONALIZATION_STATE) ==
                    Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED;
            return isInSetup || isInDeferredSetup;
        } catch (Settings.SettingNotFoundException e) {
            Slog.w(TAG, "Failed to check if the user is in restore: " + e);
            return false;
        }
    }
}
 No newline at end of file
+98 −1
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

package com.android.wallpaperbackup.tests;
package com.android.wallpaperbackup;

import static android.app.WallpaperManager.FLAG_LOCK;
import static android.app.WallpaperManager.FLAG_SYSTEM;
@@ -26,17 +26,22 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.WallpaperManager;
import android.app.backup.FullBackupDataOutput;
import android.content.ComponentName;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.UserHandle;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;

import com.android.internal.content.PackageMonitor;
import com.android.wallpaperbackup.WallpaperBackupAgent;
import com.android.wallpaperbackup.utils.ContextWithServiceOverrides;

@@ -58,6 +63,7 @@ import java.util.List;
public class WallpaperBackupAgentTest {
    private static final String SYSTEM_GENERATION = "system_gen";
    private static final String LOCK_GENERATION = "lock_gen";
    private static final String TEST_WALLPAPER_PACKAGE = "wallpaper_package";

    private static final int TEST_SYSTEM_WALLPAPER_ID = 1;
    private static final int TEST_LOCK_WALLPAPER_ID = 2;
@@ -66,11 +72,13 @@ public class WallpaperBackupAgentTest {
    @Mock private WallpaperManager mWallpaperManager;
    @Mock private SharedPreferences mSharedPreferences;
    @Mock private SharedPreferences.Editor mSharedPreferenceEditor;
    @Mock private Context mMockContext;

    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();

    private ContextWithServiceOverrides mContext;
    private IsolatedWallpaperBackupAgent mWallpaperBackupAgent;
    private ComponentName mWallpaperComponent;

    @Before
    public void setUp() {
@@ -88,6 +96,8 @@ public class WallpaperBackupAgentTest {
        mWallpaperBackupAgent = new IsolatedWallpaperBackupAgent(mTemporaryFolder.getRoot());
        mWallpaperBackupAgent.attach(mContext);
        mWallpaperBackupAgent.onCreate();

        mWallpaperComponent = new ComponentName(TEST_WALLPAPER_PACKAGE, "");
    }

    @Test
@@ -130,6 +140,69 @@ public class WallpaperBackupAgentTest {
        inOrder.verify(mSharedPreferenceEditor).apply();
    }

    @Test
    public void updateWallpaperComponent_doesApplyLater() throws IOException {
        mWallpaperBackupAgent.mIsDeviceInRestore = true;

        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
                /* applyToLock */ true);

        // Imitate wallpaper component installation.
        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
                /* uid */0);

        verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent);
        verify(mWallpaperManager, times(1)).clear(eq(FLAG_LOCK));
    }

    @Test
    public void updateWallpaperComponent_applyToLockFalse_doesApplyLaterOnlyToMainScreen()
            throws IOException {
        mWallpaperBackupAgent.mIsDeviceInRestore = true;

        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
                /* applyToLock */ false);

        // Imitate wallpaper component installation.
        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
                /* uid */0);

        verify(mWallpaperManager, times(1)).setWallpaperComponent(mWallpaperComponent);
        verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
    }

    @Test
    public void updateWallpaperComponent_deviceNotInRestore_doesNotApply()
            throws IOException {
        mWallpaperBackupAgent.mIsDeviceInRestore = false;

        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
                /* applyToLock */ true);

        // Imitate wallpaper component installation.
        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(TEST_WALLPAPER_PACKAGE,
                /* uid */0);

        verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent);
        verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
    }

    @Test
    public void updateWallpaperComponent_differentPackageInstalled_doesNotApply()
            throws IOException {
        mWallpaperBackupAgent.mIsDeviceInRestore = false;

        mWallpaperBackupAgent.updateWallpaperComponent(mWallpaperComponent,
                /* applyToLock */ true);

        // Imitate "wrong" wallpaper component installation.
        mWallpaperBackupAgent.mWallpaperPackageMonitor.onPackageAdded(/* packageName */"",
                /* uid */0);

        verify(mWallpaperManager, never()).setWallpaperComponent(mWallpaperComponent);
        verify(mWallpaperManager, never()).clear(eq(FLAG_LOCK));
    }

    private void mockUnbackedUpState() {
        mockCurrentWallpapers(TEST_SYSTEM_WALLPAPER_ID, TEST_LOCK_WALLPAPER_ID);
        when(mSharedPreferences.getInt(eq(SYSTEM_GENERATION), eq(-1))).thenReturn(-1);
@@ -162,6 +235,8 @@ public class WallpaperBackupAgentTest {
    private class IsolatedWallpaperBackupAgent extends WallpaperBackupAgent {
        File mWallpaperBaseDirectory;
        List<File> mBackedUpFiles = new ArrayList<>();
        PackageMonitor mWallpaperPackageMonitor;
        boolean mIsDeviceInRestore = false;

        IsolatedWallpaperBackupAgent(File wallpaperBaseDirectory) {
            mWallpaperBaseDirectory = wallpaperBaseDirectory;
@@ -181,5 +256,27 @@ public class WallpaperBackupAgentTest {
        public SharedPreferences getSharedPreferences(File file, int mode) {
            return mSharedPreferences;
        }

        @Override
        boolean servicePackageExists(ComponentName comp) {
            return false;
        }

        @Override
        boolean isDeviceInRestore() {
            return mIsDeviceInRestore;
        }

        @Override
        PackageMonitor getWallpaperPackageMonitor(ComponentName componentName,
                boolean applyToLock) {
            mWallpaperPackageMonitor = super.getWallpaperPackageMonitor(componentName, applyToLock);
            return mWallpaperPackageMonitor;
        }

        @Override
        public Context getBaseContext() {
            return mMockContext;
        }
    }
}