WallpaperManagerService.java revision 28f0877073e0ebc59f1eeeb6e0d54b614b9d3fa5
1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.wallpaper; 18 19import static android.os.ParcelFileDescriptor.*; 20 21import android.app.ActivityManagerNative; 22import android.app.AppGlobals; 23import android.app.IUserSwitchObserver; 24import android.app.IWallpaperManager; 25import android.app.IWallpaperManagerCallback; 26import android.app.PendingIntent; 27import android.app.WallpaperInfo; 28import android.app.WallpaperManager; 29import android.app.backup.BackupManager; 30import android.app.backup.WallpaperBackupHelper; 31import android.content.BroadcastReceiver; 32import android.content.ComponentName; 33import android.content.Context; 34import android.content.Intent; 35import android.content.IntentFilter; 36import android.content.ServiceConnection; 37import android.content.pm.IPackageManager; 38import android.content.pm.PackageManager; 39import android.content.pm.ResolveInfo; 40import android.content.pm.ServiceInfo; 41import android.content.pm.PackageManager.NameNotFoundException; 42import android.content.pm.UserInfo; 43import android.content.res.Resources; 44import android.graphics.Point; 45import android.os.Binder; 46import android.os.Bundle; 47import android.os.Environment; 48import android.os.FileUtils; 49import android.os.IBinder; 50import android.os.IRemoteCallback; 51import android.os.RemoteException; 52import android.os.FileObserver; 53import android.os.ParcelFileDescriptor; 54import android.os.RemoteCallbackList; 55import android.os.SELinux; 56import android.os.ServiceManager; 57import android.os.SystemClock; 58import android.os.UserHandle; 59import android.os.UserManager; 60import android.service.wallpaper.IWallpaperConnection; 61import android.service.wallpaper.IWallpaperEngine; 62import android.service.wallpaper.IWallpaperService; 63import android.service.wallpaper.WallpaperService; 64import android.util.Slog; 65import android.util.SparseArray; 66import android.util.Xml; 67import android.view.Display; 68import android.view.IWindowManager; 69import android.view.WindowManager; 70 71import java.io.FileDescriptor; 72import java.io.IOException; 73import java.io.InputStream; 74import java.io.File; 75import java.io.FileNotFoundException; 76import java.io.FileInputStream; 77import java.io.FileOutputStream; 78import java.io.PrintWriter; 79import java.util.List; 80 81import org.xmlpull.v1.XmlPullParser; 82import org.xmlpull.v1.XmlPullParserException; 83import org.xmlpull.v1.XmlSerializer; 84 85import com.android.internal.content.PackageMonitor; 86import com.android.internal.util.FastXmlSerializer; 87import com.android.internal.util.JournaledFile; 88 89public class WallpaperManagerService extends IWallpaperManager.Stub { 90 static final String TAG = "WallpaperManagerService"; 91 static final boolean DEBUG = false; 92 93 final Object mLock = new Object[0]; 94 95 /** 96 * Minimum time between crashes of a wallpaper service for us to consider 97 * restarting it vs. just reverting to the static wallpaper. 98 */ 99 static final long MIN_WALLPAPER_CRASH_TIME = 10000; 100 static final String WALLPAPER = "wallpaper"; 101 static final String WALLPAPER_INFO = "wallpaper_info.xml"; 102 /** 103 * Name of the component used to display bitmap wallpapers from either the gallery or 104 * built-in wallpapers. 105 */ 106 static final ComponentName IMAGE_WALLPAPER = new ComponentName("com.android.systemui", 107 "com.android.systemui.ImageWallpaper"); 108 109 /** 110 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks 111 * that the wallpaper has changed. The CREATE is triggered when there is no 112 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered 113 * everytime the wallpaper is changed. 114 */ 115 private class WallpaperObserver extends FileObserver { 116 117 final WallpaperData mWallpaper; 118 final File mWallpaperDir; 119 final File mWallpaperFile; 120 121 public WallpaperObserver(WallpaperData wallpaper) { 122 super(getWallpaperDir(wallpaper.userId).getAbsolutePath(), 123 CLOSE_WRITE | DELETE | DELETE_SELF); 124 mWallpaperDir = getWallpaperDir(wallpaper.userId); 125 mWallpaper = wallpaper; 126 mWallpaperFile = new File(mWallpaperDir, WALLPAPER); 127 } 128 129 @Override 130 public void onEvent(int event, String path) { 131 if (path == null) { 132 return; 133 } 134 synchronized (mLock) { 135 // changing the wallpaper means we'll need to back up the new one 136 long origId = Binder.clearCallingIdentity(); 137 BackupManager bm = new BackupManager(mContext); 138 bm.dataChanged(); 139 Binder.restoreCallingIdentity(origId); 140 141 File changedFile = new File(mWallpaperDir, path); 142 if (mWallpaperFile.equals(changedFile)) { 143 notifyCallbacksLocked(mWallpaper); 144 if (mWallpaper.wallpaperComponent == null || event != CLOSE_WRITE 145 || mWallpaper.imageWallpaperPending) { 146 if (event == CLOSE_WRITE) { 147 mWallpaper.imageWallpaperPending = false; 148 } 149 bindWallpaperComponentLocked(IMAGE_WALLPAPER, true, 150 false, mWallpaper, null); 151 saveSettingsLocked(mWallpaper); 152 } 153 } 154 } 155 } 156 } 157 158 final Context mContext; 159 final IWindowManager mIWindowManager; 160 final IPackageManager mIPackageManager; 161 final MyPackageMonitor mMonitor; 162 WallpaperData mLastWallpaper; 163 164 SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>(); 165 166 int mCurrentUserId; 167 168 static class WallpaperData { 169 170 int userId; 171 172 File wallpaperFile; 173 174 /** 175 * Client is currently writing a new image wallpaper. 176 */ 177 boolean imageWallpaperPending; 178 179 /** 180 * Resource name if using a picture from the wallpaper gallery 181 */ 182 String name = ""; 183 184 /** 185 * The component name of the currently set live wallpaper. 186 */ 187 ComponentName wallpaperComponent; 188 189 /** 190 * The component name of the wallpaper that should be set next. 191 */ 192 ComponentName nextWallpaperComponent; 193 194 WallpaperConnection connection; 195 long lastDiedTime; 196 boolean wallpaperUpdating; 197 WallpaperObserver wallpaperObserver; 198 199 /** 200 * List of callbacks registered they should each be notified when the wallpaper is changed. 201 */ 202 private RemoteCallbackList<IWallpaperManagerCallback> callbacks 203 = new RemoteCallbackList<IWallpaperManagerCallback>(); 204 205 int width = -1; 206 int height = -1; 207 208 WallpaperData(int userId) { 209 this.userId = userId; 210 wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER); 211 } 212 } 213 214 class WallpaperConnection extends IWallpaperConnection.Stub 215 implements ServiceConnection { 216 final WallpaperInfo mInfo; 217 final Binder mToken = new Binder(); 218 IWallpaperService mService; 219 IWallpaperEngine mEngine; 220 WallpaperData mWallpaper; 221 IRemoteCallback mReply; 222 223 boolean mDimensionsChanged = false; 224 225 public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) { 226 mInfo = info; 227 mWallpaper = wallpaper; 228 } 229 230 @Override 231 public void onServiceConnected(ComponentName name, IBinder service) { 232 synchronized (mLock) { 233 if (mWallpaper.connection == this) { 234 mService = IWallpaperService.Stub.asInterface(service); 235 attachServiceLocked(this, mWallpaper); 236 // XXX should probably do saveSettingsLocked() later 237 // when we have an engine, but I'm not sure about 238 // locking there and anyway we always need to be able to 239 // recover if there is something wrong. 240 saveSettingsLocked(mWallpaper); 241 } 242 } 243 } 244 245 @Override 246 public void onServiceDisconnected(ComponentName name) { 247 synchronized (mLock) { 248 mService = null; 249 mEngine = null; 250 if (mWallpaper.connection == this) { 251 Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent); 252 if (!mWallpaper.wallpaperUpdating 253 && mWallpaper.userId == mCurrentUserId) { 254 // There is a race condition which causes 255 // {@link #mWallpaper.wallpaperUpdating} to be false even if it is 256 // currently updating since the broadcast notifying us is async. 257 // This race is overcome by the general rule that we only reset the 258 // wallpaper if its service was shut down twice 259 // during {@link #MIN_WALLPAPER_CRASH_TIME} millis. 260 if (mWallpaper.lastDiedTime != 0 261 && mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME 262 > SystemClock.uptimeMillis()) { 263 Slog.w(TAG, "Reverting to built-in wallpaper!"); 264 clearWallpaperLocked(true, mWallpaper.userId, null); 265 } else { 266 mWallpaper.lastDiedTime = SystemClock.uptimeMillis(); 267 } 268 } 269 } 270 } 271 } 272 273 @Override 274 public void attachEngine(IWallpaperEngine engine) { 275 synchronized (mLock) { 276 mEngine = engine; 277 if (mDimensionsChanged) { 278 try { 279 mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height); 280 } catch (RemoteException e) { 281 Slog.w(TAG, "Failed to set wallpaper dimensions", e); 282 } 283 mDimensionsChanged = false; 284 } 285 } 286 } 287 288 @Override 289 public void engineShown(IWallpaperEngine engine) { 290 synchronized (mLock) { 291 if (mReply != null) { 292 long ident = Binder.clearCallingIdentity(); 293 try { 294 mReply.sendResult(null); 295 } catch (RemoteException e) { 296 Binder.restoreCallingIdentity(ident); 297 } 298 mReply = null; 299 } 300 } 301 } 302 303 @Override 304 public ParcelFileDescriptor setWallpaper(String name) { 305 synchronized (mLock) { 306 if (mWallpaper.connection == this) { 307 return updateWallpaperBitmapLocked(name, mWallpaper); 308 } 309 return null; 310 } 311 } 312 } 313 314 class MyPackageMonitor extends PackageMonitor { 315 @Override 316 public void onPackageUpdateFinished(String packageName, int uid) { 317 synchronized (mLock) { 318 if (mCurrentUserId != getChangingUserId()) { 319 return; 320 } 321 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId); 322 if (wallpaper != null) { 323 if (wallpaper.wallpaperComponent != null 324 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) { 325 wallpaper.wallpaperUpdating = false; 326 ComponentName comp = wallpaper.wallpaperComponent; 327 clearWallpaperComponentLocked(wallpaper); 328 if (!bindWallpaperComponentLocked(comp, false, false, 329 wallpaper, null)) { 330 Slog.w(TAG, "Wallpaper no longer available; reverting to default"); 331 clearWallpaperLocked(false, wallpaper.userId, null); 332 } 333 } 334 } 335 } 336 } 337 338 @Override 339 public void onPackageModified(String packageName) { 340 synchronized (mLock) { 341 if (mCurrentUserId != getChangingUserId()) { 342 return; 343 } 344 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId); 345 if (wallpaper != null) { 346 if (wallpaper.wallpaperComponent == null 347 || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) { 348 return; 349 } 350 doPackagesChangedLocked(true, wallpaper); 351 } 352 } 353 } 354 355 @Override 356 public void onPackageUpdateStarted(String packageName, int uid) { 357 synchronized (mLock) { 358 if (mCurrentUserId != getChangingUserId()) { 359 return; 360 } 361 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId); 362 if (wallpaper != null) { 363 if (wallpaper.wallpaperComponent != null 364 && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) { 365 wallpaper.wallpaperUpdating = true; 366 } 367 } 368 } 369 } 370 371 @Override 372 public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) { 373 synchronized (mLock) { 374 boolean changed = false; 375 if (mCurrentUserId != getChangingUserId()) { 376 return false; 377 } 378 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId); 379 if (wallpaper != null) { 380 boolean res = doPackagesChangedLocked(doit, wallpaper); 381 changed |= res; 382 } 383 return changed; 384 } 385 } 386 387 @Override 388 public void onSomePackagesChanged() { 389 synchronized (mLock) { 390 if (mCurrentUserId != getChangingUserId()) { 391 return; 392 } 393 WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId); 394 if (wallpaper != null) { 395 doPackagesChangedLocked(true, wallpaper); 396 } 397 } 398 } 399 400 boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) { 401 boolean changed = false; 402 if (wallpaper.wallpaperComponent != null) { 403 int change = isPackageDisappearing(wallpaper.wallpaperComponent 404 .getPackageName()); 405 if (change == PACKAGE_PERMANENT_CHANGE 406 || change == PACKAGE_TEMPORARY_CHANGE) { 407 changed = true; 408 if (doit) { 409 Slog.w(TAG, "Wallpaper uninstalled, removing: " 410 + wallpaper.wallpaperComponent); 411 clearWallpaperLocked(false, wallpaper.userId, null); 412 } 413 } 414 } 415 if (wallpaper.nextWallpaperComponent != null) { 416 int change = isPackageDisappearing(wallpaper.nextWallpaperComponent 417 .getPackageName()); 418 if (change == PACKAGE_PERMANENT_CHANGE 419 || change == PACKAGE_TEMPORARY_CHANGE) { 420 wallpaper.nextWallpaperComponent = null; 421 } 422 } 423 if (wallpaper.wallpaperComponent != null 424 && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) { 425 try { 426 mContext.getPackageManager().getServiceInfo( 427 wallpaper.wallpaperComponent, 0); 428 } catch (NameNotFoundException e) { 429 Slog.w(TAG, "Wallpaper component gone, removing: " 430 + wallpaper.wallpaperComponent); 431 clearWallpaperLocked(false, wallpaper.userId, null); 432 } 433 } 434 if (wallpaper.nextWallpaperComponent != null 435 && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) { 436 try { 437 mContext.getPackageManager().getServiceInfo( 438 wallpaper.nextWallpaperComponent, 0); 439 } catch (NameNotFoundException e) { 440 wallpaper.nextWallpaperComponent = null; 441 } 442 } 443 return changed; 444 } 445 } 446 447 public WallpaperManagerService(Context context) { 448 if (DEBUG) Slog.v(TAG, "WallpaperService startup"); 449 mContext = context; 450 mIWindowManager = IWindowManager.Stub.asInterface( 451 ServiceManager.getService(Context.WINDOW_SERVICE)); 452 mIPackageManager = AppGlobals.getPackageManager(); 453 mMonitor = new MyPackageMonitor(); 454 mMonitor.register(context, null, UserHandle.ALL, true); 455 getWallpaperDir(UserHandle.USER_OWNER).mkdirs(); 456 loadSettingsLocked(UserHandle.USER_OWNER); 457 } 458 459 private static File getWallpaperDir(int userId) { 460 return Environment.getUserSystemDirectory(userId); 461 } 462 463 @Override 464 protected void finalize() throws Throwable { 465 super.finalize(); 466 for (int i = 0; i < mWallpaperMap.size(); i++) { 467 WallpaperData wallpaper = mWallpaperMap.valueAt(i); 468 wallpaper.wallpaperObserver.stopWatching(); 469 } 470 } 471 472 public void systemRunning() { 473 if (DEBUG) Slog.v(TAG, "systemReady"); 474 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER); 475 switchWallpaper(wallpaper, null); 476 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper); 477 wallpaper.wallpaperObserver.startWatching(); 478 479 IntentFilter userFilter = new IntentFilter(); 480 userFilter.addAction(Intent.ACTION_USER_REMOVED); 481 userFilter.addAction(Intent.ACTION_USER_STOPPING); 482 mContext.registerReceiver(new BroadcastReceiver() { 483 @Override 484 public void onReceive(Context context, Intent intent) { 485 String action = intent.getAction(); 486 if (Intent.ACTION_USER_REMOVED.equals(action)) { 487 onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 488 UserHandle.USER_NULL)); 489 } 490 // TODO: Race condition causing problems when cleaning up on stopping a user. 491 // Comment this out for now. 492 // else if (Intent.ACTION_USER_STOPPING.equals(action)) { 493 // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 494 // UserHandle.USER_NULL)); 495 // } 496 } 497 }, userFilter); 498 499 try { 500 ActivityManagerNative.getDefault().registerUserSwitchObserver( 501 new IUserSwitchObserver.Stub() { 502 @Override 503 public void onUserSwitching(int newUserId, IRemoteCallback reply) { 504 switchUser(newUserId, reply); 505 } 506 507 @Override 508 public void onUserSwitchComplete(int newUserId) throws RemoteException { 509 } 510 }); 511 } catch (RemoteException e) { 512 // TODO Auto-generated catch block 513 e.printStackTrace(); 514 } 515 } 516 517 /** Called by SystemBackupAgent */ 518 public String getName() { 519 // Verify caller is the system 520 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 521 throw new RuntimeException("getName() can only be called from the system process"); 522 } 523 synchronized (mLock) { 524 return mWallpaperMap.get(0).name; 525 } 526 } 527 528 void onStoppingUser(int userId) { 529 if (userId < 1) return; 530 synchronized (mLock) { 531 WallpaperData wallpaper = mWallpaperMap.get(userId); 532 if (wallpaper != null) { 533 if (wallpaper.wallpaperObserver != null) { 534 wallpaper.wallpaperObserver.stopWatching(); 535 wallpaper.wallpaperObserver = null; 536 } 537 mWallpaperMap.remove(userId); 538 } 539 } 540 } 541 542 void onRemoveUser(int userId) { 543 if (userId < 1) return; 544 synchronized (mLock) { 545 onStoppingUser(userId); 546 File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER); 547 wallpaperFile.delete(); 548 File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO); 549 wallpaperInfoFile.delete(); 550 } 551 } 552 553 void switchUser(int userId, IRemoteCallback reply) { 554 synchronized (mLock) { 555 mCurrentUserId = userId; 556 WallpaperData wallpaper = mWallpaperMap.get(userId); 557 if (wallpaper == null) { 558 wallpaper = new WallpaperData(userId); 559 mWallpaperMap.put(userId, wallpaper); 560 loadSettingsLocked(userId); 561 } 562 // Not started watching yet, in case wallpaper data was loaded for other reasons. 563 if (wallpaper.wallpaperObserver == null) { 564 wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper); 565 wallpaper.wallpaperObserver.startWatching(); 566 } 567 switchWallpaper(wallpaper, reply); 568 } 569 } 570 571 void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) { 572 synchronized (mLock) { 573 RuntimeException e = null; 574 try { 575 ComponentName cname = wallpaper.wallpaperComponent != null ? 576 wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent; 577 if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) { 578 return; 579 } 580 } catch (RuntimeException e1) { 581 e = e1; 582 } 583 Slog.w(TAG, "Failure starting previous wallpaper", e); 584 clearWallpaperLocked(false, wallpaper.userId, reply); 585 } 586 } 587 588 public void clearWallpaper() { 589 if (DEBUG) Slog.v(TAG, "clearWallpaper"); 590 synchronized (mLock) { 591 clearWallpaperLocked(false, UserHandle.getCallingUserId(), null); 592 } 593 } 594 595 void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) { 596 WallpaperData wallpaper = mWallpaperMap.get(userId); 597 File f = new File(getWallpaperDir(userId), WALLPAPER); 598 if (f.exists()) { 599 f.delete(); 600 } 601 final long ident = Binder.clearCallingIdentity(); 602 RuntimeException e = null; 603 try { 604 wallpaper.imageWallpaperPending = false; 605 if (userId != mCurrentUserId) return; 606 if (bindWallpaperComponentLocked(defaultFailed 607 ? IMAGE_WALLPAPER 608 : null, true, false, wallpaper, reply)) { 609 return; 610 } 611 } catch (IllegalArgumentException e1) { 612 e = e1; 613 } finally { 614 Binder.restoreCallingIdentity(ident); 615 } 616 617 // This can happen if the default wallpaper component doesn't 618 // exist. This should be a system configuration problem, but 619 // let's not let it crash the system and just live with no 620 // wallpaper. 621 Slog.e(TAG, "Default wallpaper component not found!", e); 622 clearWallpaperComponentLocked(wallpaper); 623 if (reply != null) { 624 try { 625 reply.sendResult(null); 626 } catch (RemoteException e1) { 627 } 628 } 629 } 630 631 public boolean hasNamedWallpaper(String name) { 632 synchronized (mLock) { 633 List<UserInfo> users; 634 long ident = Binder.clearCallingIdentity(); 635 try { 636 users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers(); 637 } finally { 638 Binder.restoreCallingIdentity(ident); 639 } 640 for (UserInfo user: users) { 641 WallpaperData wd = mWallpaperMap.get(user.id); 642 if (wd == null) { 643 // User hasn't started yet, so load her settings to peek at the wallpaper 644 loadSettingsLocked(user.id); 645 wd = mWallpaperMap.get(user.id); 646 } 647 if (wd != null && name.equals(wd.name)) { 648 return true; 649 } 650 } 651 } 652 return false; 653 } 654 655 private Point getDefaultDisplaySize() { 656 Point p = new Point(); 657 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 658 Display d = wm.getDefaultDisplay(); 659 d.getRealSize(p); 660 return p; 661 } 662 663 public void setDimensionHints(int width, int height) throws RemoteException { 664 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS); 665 synchronized (mLock) { 666 int userId = UserHandle.getCallingUserId(); 667 WallpaperData wallpaper = mWallpaperMap.get(userId); 668 if (wallpaper == null) { 669 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId); 670 } 671 if (width <= 0 || height <= 0) { 672 throw new IllegalArgumentException("width and height must be > 0"); 673 } 674 // Make sure it is at least as large as the display. 675 Point displaySize = getDefaultDisplaySize(); 676 width = Math.max(width, displaySize.x); 677 height = Math.max(height, displaySize.y); 678 679 if (width != wallpaper.width || height != wallpaper.height) { 680 wallpaper.width = width; 681 wallpaper.height = height; 682 saveSettingsLocked(wallpaper); 683 if (mCurrentUserId != userId) return; // Don't change the properties now 684 if (wallpaper.connection != null) { 685 if (wallpaper.connection.mEngine != null) { 686 try { 687 wallpaper.connection.mEngine.setDesiredSize( 688 width, height); 689 } catch (RemoteException e) { 690 } 691 notifyCallbacksLocked(wallpaper); 692 } else if (wallpaper.connection.mService != null) { 693 // We've attached to the service but the engine hasn't attached back to us 694 // yet. This means it will be created with the previous dimensions, so we 695 // need to update it to the new dimensions once it attaches. 696 wallpaper.connection.mDimensionsChanged = true; 697 } 698 } 699 } 700 } 701 } 702 703 public int getWidthHint() throws RemoteException { 704 synchronized (mLock) { 705 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId()); 706 return wallpaper.width; 707 } 708 } 709 710 public int getHeightHint() throws RemoteException { 711 synchronized (mLock) { 712 WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId()); 713 return wallpaper.height; 714 } 715 } 716 717 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, 718 Bundle outParams) { 719 synchronized (mLock) { 720 // This returns the current user's wallpaper, if called by a system service. Else it 721 // returns the wallpaper for the calling user. 722 int callingUid = Binder.getCallingUid(); 723 int wallpaperUserId = 0; 724 if (callingUid == android.os.Process.SYSTEM_UID) { 725 wallpaperUserId = mCurrentUserId; 726 } else { 727 wallpaperUserId = UserHandle.getUserId(callingUid); 728 } 729 WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId); 730 try { 731 if (outParams != null) { 732 outParams.putInt("width", wallpaper.width); 733 outParams.putInt("height", wallpaper.height); 734 } 735 wallpaper.callbacks.register(cb); 736 File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER); 737 if (!f.exists()) { 738 return null; 739 } 740 return ParcelFileDescriptor.open(f, MODE_READ_ONLY); 741 } catch (FileNotFoundException e) { 742 /* Shouldn't happen as we check to see if the file exists */ 743 Slog.w(TAG, "Error getting wallpaper", e); 744 } 745 return null; 746 } 747 } 748 749 public WallpaperInfo getWallpaperInfo() { 750 int userId = UserHandle.getCallingUserId(); 751 synchronized (mLock) { 752 WallpaperData wallpaper = mWallpaperMap.get(userId); 753 if (wallpaper.connection != null) { 754 return wallpaper.connection.mInfo; 755 } 756 return null; 757 } 758 } 759 760 public ParcelFileDescriptor setWallpaper(String name) { 761 checkPermission(android.Manifest.permission.SET_WALLPAPER); 762 synchronized (mLock) { 763 if (DEBUG) Slog.v(TAG, "setWallpaper"); 764 int userId = UserHandle.getCallingUserId(); 765 WallpaperData wallpaper = mWallpaperMap.get(userId); 766 if (wallpaper == null) { 767 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId); 768 } 769 final long ident = Binder.clearCallingIdentity(); 770 try { 771 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper); 772 if (pfd != null) { 773 wallpaper.imageWallpaperPending = true; 774 } 775 return pfd; 776 } finally { 777 Binder.restoreCallingIdentity(ident); 778 } 779 } 780 } 781 782 ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) { 783 if (name == null) name = ""; 784 try { 785 File dir = getWallpaperDir(wallpaper.userId); 786 if (!dir.exists()) { 787 dir.mkdir(); 788 FileUtils.setPermissions( 789 dir.getPath(), 790 FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH, 791 -1, -1); 792 } 793 File file = new File(dir, WALLPAPER); 794 ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, 795 MODE_CREATE|MODE_READ_WRITE); 796 if (!SELinux.restorecon(file)) { 797 return null; 798 } 799 wallpaper.name = name; 800 return fd; 801 } catch (FileNotFoundException e) { 802 Slog.w(TAG, "Error setting wallpaper", e); 803 } 804 return null; 805 } 806 807 public void setWallpaperComponent(ComponentName name) { 808 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); 809 synchronized (mLock) { 810 if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name); 811 int userId = UserHandle.getCallingUserId(); 812 WallpaperData wallpaper = mWallpaperMap.get(userId); 813 if (wallpaper == null) { 814 throw new IllegalStateException("Wallpaper not yet initialized for user " + userId); 815 } 816 final long ident = Binder.clearCallingIdentity(); 817 try { 818 wallpaper.imageWallpaperPending = false; 819 bindWallpaperComponentLocked(name, false, true, wallpaper, null); 820 } finally { 821 Binder.restoreCallingIdentity(ident); 822 } 823 } 824 } 825 826 boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force, 827 boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) { 828 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName); 829 // Has the component changed? 830 if (!force) { 831 if (wallpaper.connection != null) { 832 if (wallpaper.wallpaperComponent == null) { 833 if (componentName == null) { 834 if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default"); 835 // Still using default wallpaper. 836 return true; 837 } 838 } else if (wallpaper.wallpaperComponent.equals(componentName)) { 839 // Changing to same wallpaper. 840 if (DEBUG) Slog.v(TAG, "same wallpaper"); 841 return true; 842 } 843 } 844 } 845 846 try { 847 if (componentName == null) { 848 componentName = WallpaperManager.getDefaultWallpaperComponent(mContext); 849 if (componentName == null) { 850 // Fall back to static image wallpaper 851 componentName = IMAGE_WALLPAPER; 852 //clearWallpaperComponentLocked(); 853 //return; 854 if (DEBUG) Slog.v(TAG, "Using image wallpaper"); 855 } 856 } 857 int serviceUserId = wallpaper.userId; 858 ServiceInfo si = mIPackageManager.getServiceInfo(componentName, 859 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId); 860 if (si == null) { 861 // The wallpaper component we're trying to use doesn't exist 862 Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable"); 863 return false; 864 } 865 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) { 866 String msg = "Selected service does not require " 867 + android.Manifest.permission.BIND_WALLPAPER 868 + ": " + componentName; 869 if (fromUser) { 870 throw new SecurityException(msg); 871 } 872 Slog.w(TAG, msg); 873 return false; 874 } 875 876 WallpaperInfo wi = null; 877 878 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE); 879 if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) { 880 // Make sure the selected service is actually a wallpaper service. 881 List<ResolveInfo> ris = 882 mIPackageManager.queryIntentServices(intent, 883 intent.resolveTypeIfNeeded(mContext.getContentResolver()), 884 PackageManager.GET_META_DATA, serviceUserId); 885 for (int i=0; i<ris.size(); i++) { 886 ServiceInfo rsi = ris.get(i).serviceInfo; 887 if (rsi.name.equals(si.name) && 888 rsi.packageName.equals(si.packageName)) { 889 try { 890 wi = new WallpaperInfo(mContext, ris.get(i)); 891 } catch (XmlPullParserException e) { 892 if (fromUser) { 893 throw new IllegalArgumentException(e); 894 } 895 Slog.w(TAG, e); 896 return false; 897 } catch (IOException e) { 898 if (fromUser) { 899 throw new IllegalArgumentException(e); 900 } 901 Slog.w(TAG, e); 902 return false; 903 } 904 break; 905 } 906 } 907 if (wi == null) { 908 String msg = "Selected service is not a wallpaper: " 909 + componentName; 910 if (fromUser) { 911 throw new SecurityException(msg); 912 } 913 Slog.w(TAG, msg); 914 return false; 915 } 916 } 917 918 // Bind the service! 919 if (DEBUG) Slog.v(TAG, "Binding to:" + componentName); 920 WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper); 921 intent.setComponent(componentName); 922 intent.putExtra(Intent.EXTRA_CLIENT_LABEL, 923 com.android.internal.R.string.wallpaper_binding_label); 924 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser( 925 mContext, 0, 926 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER), 927 mContext.getText(com.android.internal.R.string.chooser_wallpaper)), 928 0, null, new UserHandle(serviceUserId))); 929 if (!mContext.bindServiceAsUser(intent, newConn, 930 Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI, 931 new UserHandle(serviceUserId))) { 932 String msg = "Unable to bind service: " 933 + componentName; 934 if (fromUser) { 935 throw new IllegalArgumentException(msg); 936 } 937 Slog.w(TAG, msg); 938 return false; 939 } 940 if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) { 941 detachWallpaperLocked(mLastWallpaper); 942 } 943 wallpaper.wallpaperComponent = componentName; 944 wallpaper.connection = newConn; 945 newConn.mReply = reply; 946 try { 947 if (wallpaper.userId == mCurrentUserId) { 948 if (DEBUG) 949 Slog.v(TAG, "Adding window token: " + newConn.mToken); 950 mIWindowManager.addWindowToken(newConn.mToken, 951 WindowManager.LayoutParams.TYPE_WALLPAPER); 952 mLastWallpaper = wallpaper; 953 } 954 } catch (RemoteException e) { 955 } 956 } catch (RemoteException e) { 957 String msg = "Remote exception for " + componentName + "\n" + e; 958 if (fromUser) { 959 throw new IllegalArgumentException(msg); 960 } 961 Slog.w(TAG, msg); 962 return false; 963 } 964 return true; 965 } 966 967 void detachWallpaperLocked(WallpaperData wallpaper) { 968 if (wallpaper.connection != null) { 969 if (wallpaper.connection.mReply != null) { 970 try { 971 wallpaper.connection.mReply.sendResult(null); 972 } catch (RemoteException e) { 973 } 974 wallpaper.connection.mReply = null; 975 } 976 if (wallpaper.connection.mEngine != null) { 977 try { 978 wallpaper.connection.mEngine.destroy(); 979 } catch (RemoteException e) { 980 } 981 } 982 mContext.unbindService(wallpaper.connection); 983 try { 984 if (DEBUG) 985 Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken); 986 mIWindowManager.removeWindowToken(wallpaper.connection.mToken); 987 } catch (RemoteException e) { 988 } 989 wallpaper.connection.mService = null; 990 wallpaper.connection.mEngine = null; 991 wallpaper.connection = null; 992 } 993 } 994 995 void clearWallpaperComponentLocked(WallpaperData wallpaper) { 996 wallpaper.wallpaperComponent = null; 997 detachWallpaperLocked(wallpaper); 998 } 999 1000 void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) { 1001 try { 1002 conn.mService.attach(conn, conn.mToken, 1003 WindowManager.LayoutParams.TYPE_WALLPAPER, false, 1004 wallpaper.width, wallpaper.height); 1005 } catch (RemoteException e) { 1006 Slog.w(TAG, "Failed attaching wallpaper; clearing", e); 1007 if (!wallpaper.wallpaperUpdating) { 1008 bindWallpaperComponentLocked(null, false, false, wallpaper, null); 1009 } 1010 } 1011 } 1012 1013 private void notifyCallbacksLocked(WallpaperData wallpaper) { 1014 final int n = wallpaper.callbacks.beginBroadcast(); 1015 for (int i = 0; i < n; i++) { 1016 try { 1017 wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged(); 1018 } catch (RemoteException e) { 1019 1020 // The RemoteCallbackList will take care of removing 1021 // the dead object for us. 1022 } 1023 } 1024 wallpaper.callbacks.finishBroadcast(); 1025 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED); 1026 mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId)); 1027 } 1028 1029 private void checkPermission(String permission) { 1030 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) { 1031 throw new SecurityException("Access denied to process: " + Binder.getCallingPid() 1032 + ", must have permission " + permission); 1033 } 1034 } 1035 1036 private static JournaledFile makeJournaledFile(int userId) { 1037 final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath(); 1038 return new JournaledFile(new File(base), new File(base + ".tmp")); 1039 } 1040 1041 private void saveSettingsLocked(WallpaperData wallpaper) { 1042 JournaledFile journal = makeJournaledFile(wallpaper.userId); 1043 FileOutputStream stream = null; 1044 try { 1045 stream = new FileOutputStream(journal.chooseForWrite(), false); 1046 XmlSerializer out = new FastXmlSerializer(); 1047 out.setOutput(stream, "utf-8"); 1048 out.startDocument(null, true); 1049 1050 out.startTag(null, "wp"); 1051 out.attribute(null, "width", Integer.toString(wallpaper.width)); 1052 out.attribute(null, "height", Integer.toString(wallpaper.height)); 1053 out.attribute(null, "name", wallpaper.name); 1054 if (wallpaper.wallpaperComponent != null 1055 && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) { 1056 out.attribute(null, "component", 1057 wallpaper.wallpaperComponent.flattenToShortString()); 1058 } 1059 out.endTag(null, "wp"); 1060 1061 out.endDocument(); 1062 stream.close(); 1063 journal.commit(); 1064 } catch (IOException e) { 1065 try { 1066 if (stream != null) { 1067 stream.close(); 1068 } 1069 } catch (IOException ex) { 1070 // Ignore 1071 } 1072 journal.rollback(); 1073 } 1074 } 1075 1076 private void migrateFromOld() { 1077 File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY); 1078 File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY); 1079 if (oldWallpaper.exists()) { 1080 File newWallpaper = new File(getWallpaperDir(0), WALLPAPER); 1081 oldWallpaper.renameTo(newWallpaper); 1082 } 1083 if (oldInfo.exists()) { 1084 File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO); 1085 oldInfo.renameTo(newInfo); 1086 } 1087 } 1088 1089 private void loadSettingsLocked(int userId) { 1090 if (DEBUG) Slog.v(TAG, "loadSettingsLocked"); 1091 1092 JournaledFile journal = makeJournaledFile(userId); 1093 FileInputStream stream = null; 1094 File file = journal.chooseForRead(); 1095 if (!file.exists()) { 1096 // This should only happen one time, when upgrading from a legacy system 1097 migrateFromOld(); 1098 } 1099 WallpaperData wallpaper = mWallpaperMap.get(userId); 1100 if (wallpaper == null) { 1101 wallpaper = new WallpaperData(userId); 1102 mWallpaperMap.put(userId, wallpaper); 1103 } 1104 boolean success = false; 1105 try { 1106 stream = new FileInputStream(file); 1107 XmlPullParser parser = Xml.newPullParser(); 1108 parser.setInput(stream, null); 1109 1110 int type; 1111 do { 1112 type = parser.next(); 1113 if (type == XmlPullParser.START_TAG) { 1114 String tag = parser.getName(); 1115 if ("wp".equals(tag)) { 1116 wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width")); 1117 wallpaper.height = Integer.parseInt(parser 1118 .getAttributeValue(null, "height")); 1119 wallpaper.name = parser.getAttributeValue(null, "name"); 1120 String comp = parser.getAttributeValue(null, "component"); 1121 wallpaper.nextWallpaperComponent = comp != null 1122 ? ComponentName.unflattenFromString(comp) 1123 : null; 1124 if (wallpaper.nextWallpaperComponent == null 1125 || "android".equals(wallpaper.nextWallpaperComponent 1126 .getPackageName())) { 1127 wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER; 1128 } 1129 1130 if (DEBUG) { 1131 Slog.v(TAG, "mWidth:" + wallpaper.width); 1132 Slog.v(TAG, "mHeight:" + wallpaper.height); 1133 Slog.v(TAG, "mName:" + wallpaper.name); 1134 Slog.v(TAG, "mNextWallpaperComponent:" 1135 + wallpaper.nextWallpaperComponent); 1136 } 1137 } 1138 } 1139 } while (type != XmlPullParser.END_DOCUMENT); 1140 success = true; 1141 } catch (FileNotFoundException e) { 1142 Slog.w(TAG, "no current wallpaper -- first boot?"); 1143 } catch (NullPointerException e) { 1144 Slog.w(TAG, "failed parsing " + file + " " + e); 1145 } catch (NumberFormatException e) { 1146 Slog.w(TAG, "failed parsing " + file + " " + e); 1147 } catch (XmlPullParserException e) { 1148 Slog.w(TAG, "failed parsing " + file + " " + e); 1149 } catch (IOException e) { 1150 Slog.w(TAG, "failed parsing " + file + " " + e); 1151 } catch (IndexOutOfBoundsException e) { 1152 Slog.w(TAG, "failed parsing " + file + " " + e); 1153 } 1154 try { 1155 if (stream != null) { 1156 stream.close(); 1157 } 1158 } catch (IOException e) { 1159 // Ignore 1160 } 1161 1162 if (!success) { 1163 wallpaper.width = -1; 1164 wallpaper.height = -1; 1165 wallpaper.name = ""; 1166 } 1167 1168 // We always want to have some reasonable width hint. 1169 int baseSize = getMaximumSizeDimension(); 1170 if (wallpaper.width < baseSize) { 1171 wallpaper.width = baseSize; 1172 } 1173 if (wallpaper.height < baseSize) { 1174 wallpaper.height = baseSize; 1175 } 1176 } 1177 1178 private int getMaximumSizeDimension() { 1179 WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); 1180 Display d = wm.getDefaultDisplay(); 1181 return d.getMaximumSizeDimension(); 1182 } 1183 1184 // Called by SystemBackupAgent after files are restored to disk. 1185 public void settingsRestored() { 1186 // Verify caller is the system 1187 if (Binder.getCallingUid() != android.os.Process.SYSTEM_UID) { 1188 throw new RuntimeException("settingsRestored() can only be called from the system process"); 1189 } 1190 // TODO: If necessary, make it work for secondary users as well. This currently assumes 1191 // restores only to the primary user 1192 if (DEBUG) Slog.v(TAG, "settingsRestored"); 1193 WallpaperData wallpaper = null; 1194 boolean success = false; 1195 synchronized (mLock) { 1196 loadSettingsLocked(0); 1197 wallpaper = mWallpaperMap.get(0); 1198 if (wallpaper.nextWallpaperComponent != null 1199 && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) { 1200 if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false, 1201 wallpaper, null)) { 1202 // No such live wallpaper or other failure; fall back to the default 1203 // live wallpaper (since the profile being restored indicated that the 1204 // user had selected a live rather than static one). 1205 bindWallpaperComponentLocked(null, false, false, wallpaper, null); 1206 } 1207 success = true; 1208 } else { 1209 // If there's a wallpaper name, we use that. If that can't be loaded, then we 1210 // use the default. 1211 if ("".equals(wallpaper.name)) { 1212 if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty"); 1213 success = true; 1214 } else { 1215 if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource"); 1216 success = restoreNamedResourceLocked(wallpaper); 1217 } 1218 if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success); 1219 if (success) { 1220 bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false, 1221 wallpaper, null); 1222 } 1223 } 1224 } 1225 1226 if (!success) { 1227 Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'"); 1228 wallpaper.name = ""; 1229 getWallpaperDir(0).delete(); 1230 } 1231 1232 synchronized (mLock) { 1233 saveSettingsLocked(wallpaper); 1234 } 1235 } 1236 1237 boolean restoreNamedResourceLocked(WallpaperData wallpaper) { 1238 if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) { 1239 String resName = wallpaper.name.substring(4); 1240 1241 String pkg = null; 1242 int colon = resName.indexOf(':'); 1243 if (colon > 0) { 1244 pkg = resName.substring(0, colon); 1245 } 1246 1247 String ident = null; 1248 int slash = resName.lastIndexOf('/'); 1249 if (slash > 0) { 1250 ident = resName.substring(slash+1); 1251 } 1252 1253 String type = null; 1254 if (colon > 0 && slash > 0 && (slash-colon) > 1) { 1255 type = resName.substring(colon+1, slash); 1256 } 1257 1258 if (pkg != null && ident != null && type != null) { 1259 int resId = -1; 1260 InputStream res = null; 1261 FileOutputStream fos = null; 1262 try { 1263 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED); 1264 Resources r = c.getResources(); 1265 resId = r.getIdentifier(resName, null, null); 1266 if (resId == 0) { 1267 Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type 1268 + " ident=" + ident); 1269 return false; 1270 } 1271 1272 res = r.openRawResource(resId); 1273 if (wallpaper.wallpaperFile.exists()) { 1274 wallpaper.wallpaperFile.delete(); 1275 } 1276 fos = new FileOutputStream(wallpaper.wallpaperFile); 1277 1278 byte[] buffer = new byte[32768]; 1279 int amt; 1280 while ((amt=res.read(buffer)) > 0) { 1281 fos.write(buffer, 0, amt); 1282 } 1283 // mWallpaperObserver will notice the close and send the change broadcast 1284 1285 Slog.v(TAG, "Restored wallpaper: " + resName); 1286 return true; 1287 } catch (NameNotFoundException e) { 1288 Slog.e(TAG, "Package name " + pkg + " not found"); 1289 } catch (Resources.NotFoundException e) { 1290 Slog.e(TAG, "Resource not found: " + resId); 1291 } catch (IOException e) { 1292 Slog.e(TAG, "IOException while restoring wallpaper ", e); 1293 } finally { 1294 if (res != null) { 1295 try { 1296 res.close(); 1297 } catch (IOException ex) {} 1298 } 1299 if (fos != null) { 1300 FileUtils.sync(fos); 1301 try { 1302 fos.close(); 1303 } catch (IOException ex) {} 1304 } 1305 } 1306 } 1307 } 1308 return false; 1309 } 1310 1311 @Override 1312 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1313 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 1314 != PackageManager.PERMISSION_GRANTED) { 1315 1316 pw.println("Permission Denial: can't dump wallpaper service from from pid=" 1317 + Binder.getCallingPid() 1318 + ", uid=" + Binder.getCallingUid()); 1319 return; 1320 } 1321 1322 synchronized (mLock) { 1323 pw.println("Current Wallpaper Service state:"); 1324 for (int i = 0; i < mWallpaperMap.size(); i++) { 1325 WallpaperData wallpaper = mWallpaperMap.valueAt(i); 1326 pw.println(" User " + wallpaper.userId + ":"); 1327 pw.print(" mWidth="); 1328 pw.print(wallpaper.width); 1329 pw.print(" mHeight="); 1330 pw.println(wallpaper.height); 1331 pw.print(" mName="); 1332 pw.println(wallpaper.name); 1333 pw.print(" mWallpaperComponent="); 1334 pw.println(wallpaper.wallpaperComponent); 1335 if (wallpaper.connection != null) { 1336 WallpaperConnection conn = wallpaper.connection; 1337 pw.print(" Wallpaper connection "); 1338 pw.print(conn); 1339 pw.println(":"); 1340 if (conn.mInfo != null) { 1341 pw.print(" mInfo.component="); 1342 pw.println(conn.mInfo.getComponent()); 1343 } 1344 pw.print(" mToken="); 1345 pw.println(conn.mToken); 1346 pw.print(" mService="); 1347 pw.println(conn.mService); 1348 pw.print(" mEngine="); 1349 pw.println(conn.mEngine); 1350 pw.print(" mLastDiedTime="); 1351 pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis()); 1352 } 1353 } 1354 } 1355 } 1356} 1357