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
This commit is contained in:
Ruslan Tkhakokhov
2020-04-01 15:09:42 +01:00
parent be3b2304d2
commit 4f8a9d98c5
2 changed files with 174 additions and 18 deletions

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}
}