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; 18 19import static android.os.FileObserver.*; 20import static android.os.ParcelFileDescriptor.*; 21 22import android.app.IWallpaperManager; 23import android.app.IWallpaperManagerCallback; 24import android.app.PendingIntent; 25import android.app.WallpaperInfo; 26import android.backup.BackupManager; 27import android.content.ComponentName; 28import android.content.Context; 29import android.content.Intent; 30import android.content.ServiceConnection; 31import android.content.pm.PackageManager; 32import android.content.pm.ResolveInfo; 33import android.content.pm.ServiceInfo; 34import android.content.pm.PackageManager.NameNotFoundException; 35import android.content.res.Resources; 36import android.os.Binder; 37import android.os.Bundle; 38import android.os.IBinder; 39import android.os.RemoteException; 40import android.os.FileObserver; 41import android.os.ParcelFileDescriptor; 42import android.os.RemoteCallbackList; 43import android.os.ServiceManager; 44import android.os.SystemClock; 45import android.service.wallpaper.IWallpaperConnection; 46import android.service.wallpaper.IWallpaperEngine; 47import android.service.wallpaper.IWallpaperService; 48import android.service.wallpaper.WallpaperService; 49import android.util.Log; 50import android.util.Xml; 51import android.view.IWindowManager; 52import android.view.WindowManager; 53 54import java.io.FileDescriptor; 55import java.io.IOException; 56import java.io.InputStream; 57import java.io.File; 58import java.io.FileNotFoundException; 59import java.io.FileInputStream; 60import java.io.FileOutputStream; 61import java.io.PrintWriter; 62import java.util.List; 63 64import org.xmlpull.v1.XmlPullParser; 65import org.xmlpull.v1.XmlPullParserException; 66import org.xmlpull.v1.XmlSerializer; 67 68import com.android.internal.service.wallpaper.ImageWallpaper; 69import com.android.internal.util.FastXmlSerializer; 70 71class WallpaperManagerService extends IWallpaperManager.Stub { 72 static final String TAG = "WallpaperService"; 73 static final boolean DEBUG = false; 74 75 Object mLock = new Object(); 76 77 /** 78 * Minimum time between crashes of a wallpaper service for us to consider 79 * restarting it vs. just reverting to the static wallpaper. 80 */ 81 static final long MIN_WALLPAPER_CRASH_TIME = 10000; 82 83 static final File WALLPAPER_DIR = new File( 84 "/data/data/com.android.settings/files"); 85 static final String WALLPAPER = "wallpaper"; 86 static final File WALLPAPER_FILE = new File(WALLPAPER_DIR, WALLPAPER); 87 88 /** 89 * List of callbacks registered they should each be notified 90 * when the wallpaper is changed. 91 */ 92 private final RemoteCallbackList<IWallpaperManagerCallback> mCallbacks 93 = new RemoteCallbackList<IWallpaperManagerCallback>(); 94 95 /** 96 * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks 97 * that the wallpaper has changed. The CREATE is triggered when there is no 98 * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered 99 * everytime the wallpaper is changed. 100 */ 101 private final FileObserver mWallpaperObserver = new FileObserver( 102 WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE | DELETE | DELETE_SELF) { 103 @Override 104 public void onEvent(int event, String path) { 105 if (path == null) { 106 return; 107 } 108 synchronized (mLock) { 109 // changing the wallpaper means we'll need to back up the new one 110 long origId = Binder.clearCallingIdentity(); 111 BackupManager bm = new BackupManager(mContext); 112 bm.dataChanged(); 113 Binder.restoreCallingIdentity(origId); 114 115 File changedFile = new File(WALLPAPER_DIR, path); 116 if (WALLPAPER_FILE.equals(changedFile)) { 117 notifyCallbacksLocked(); 118 } 119 } 120 } 121 }; 122 123 final Context mContext; 124 final IWindowManager mIWindowManager; 125 126 int mWidth = -1; 127 int mHeight = -1; 128 129 /** 130 * Resource name if using a picture from the wallpaper gallery 131 */ 132 String mName = ""; 133 134 /** 135 * The component name of the currently set live wallpaper. 136 */ 137 ComponentName mWallpaperComponent; 138 139 /** 140 * The component name of the wallpaper that should be set next. 141 */ 142 ComponentName mNextWallpaperComponent; 143 144 /** 145 * Name of the component used to display bitmap wallpapers from either the gallery or 146 * built-in wallpapers. 147 */ 148 ComponentName mImageWallpaperComponent = new ComponentName("android", 149 ImageWallpaper.class.getName()); 150 151 WallpaperConnection mWallpaperConnection; 152 long mLastDiedTime; 153 154 class WallpaperConnection extends IWallpaperConnection.Stub 155 implements ServiceConnection { 156 final WallpaperInfo mInfo; 157 final Binder mToken = new Binder(); 158 IWallpaperService mService; 159 IWallpaperEngine mEngine; 160 161 public WallpaperConnection(WallpaperInfo info) { 162 mInfo = info; 163 } 164 165 public void onServiceConnected(ComponentName name, IBinder service) { 166 synchronized (mLock) { 167 if (mWallpaperConnection == this) { 168 mService = IWallpaperService.Stub.asInterface(service); 169 attachServiceLocked(this); 170 // XXX should probably do saveSettingsLocked() later 171 // when we have an engine, but I'm not sure about 172 // locking there and anyway we always need to be able to 173 // recover if there is something wrong. 174 saveSettingsLocked(); 175 } 176 } 177 } 178 179 public void onServiceDisconnected(ComponentName name) { 180 synchronized (mLock) { 181 mService = null; 182 mEngine = null; 183 if (mWallpaperConnection == this) { 184 Log.w(TAG, "Wallpaper service gone: " + mWallpaperComponent); 185 if ((mLastDiedTime+MIN_WALLPAPER_CRASH_TIME) 186 < SystemClock.uptimeMillis()) { 187 Log.w(TAG, "Reverting to built-in wallpaper!"); 188 bindWallpaperComponentLocked(null); 189 } 190 } 191 } 192 } 193 194 public void attachEngine(IWallpaperEngine engine) { 195 mEngine = engine; 196 } 197 198 public ParcelFileDescriptor setWallpaper(String name) { 199 synchronized (mLock) { 200 if (mWallpaperConnection == this) { 201 return updateWallpaperBitmapLocked(name); 202 } 203 return null; 204 } 205 } 206 } 207 208 public WallpaperManagerService(Context context) { 209 if (DEBUG) Log.v(TAG, "WallpaperService startup"); 210 mContext = context; 211 mIWindowManager = IWindowManager.Stub.asInterface( 212 ServiceManager.getService(Context.WINDOW_SERVICE)); 213 WALLPAPER_DIR.mkdirs(); 214 loadSettingsLocked(); 215 mWallpaperObserver.startWatching(); 216 } 217 218 @Override 219 protected void finalize() throws Throwable { 220 super.finalize(); 221 mWallpaperObserver.stopWatching(); 222 } 223 224 public void systemReady() { 225 if (DEBUG) Log.v(TAG, "systemReady"); 226 synchronized (mLock) { 227 try { 228 bindWallpaperComponentLocked(mNextWallpaperComponent); 229 } catch (RuntimeException e) { 230 Log.w(TAG, "Failure starting previous wallpaper", e); 231 try { 232 bindWallpaperComponentLocked(null); 233 } catch (RuntimeException e2) { 234 Log.w(TAG, "Failure starting default wallpaper", e2); 235 clearWallpaperComponentLocked(); 236 } 237 } 238 } 239 } 240 241 public void clearWallpaper() { 242 if (DEBUG) Log.v(TAG, "clearWallpaper"); 243 synchronized (mLock) { 244 File f = WALLPAPER_FILE; 245 if (f.exists()) { 246 f.delete(); 247 } 248 final long ident = Binder.clearCallingIdentity(); 249 try { 250 bindWallpaperComponentLocked(null); 251 } finally { 252 Binder.restoreCallingIdentity(ident); 253 } 254 } 255 } 256 257 public void setDimensionHints(int width, int height) throws RemoteException { 258 checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS); 259 260 if (width <= 0 || height <= 0) { 261 throw new IllegalArgumentException("width and height must be > 0"); 262 } 263 264 synchronized (mLock) { 265 if (width != mWidth || height != mHeight) { 266 mWidth = width; 267 mHeight = height; 268 saveSettingsLocked(); 269 if (mWallpaperConnection != null) { 270 if (mWallpaperConnection.mEngine != null) { 271 try { 272 mWallpaperConnection.mEngine.setDesiredSize( 273 width, height); 274 } catch (RemoteException e) { 275 } 276 notifyCallbacksLocked(); 277 } 278 } 279 } 280 } 281 } 282 283 public int getWidthHint() throws RemoteException { 284 synchronized (mLock) { 285 return mWidth; 286 } 287 } 288 289 public int getHeightHint() throws RemoteException { 290 synchronized (mLock) { 291 return mHeight; 292 } 293 } 294 295 public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, 296 Bundle outParams) { 297 synchronized (mLock) { 298 try { 299 if (outParams != null) { 300 outParams.putInt("width", mWidth); 301 outParams.putInt("height", mHeight); 302 } 303 mCallbacks.register(cb); 304 File f = WALLPAPER_FILE; 305 if (!f.exists()) { 306 return null; 307 } 308 return ParcelFileDescriptor.open(f, MODE_READ_ONLY); 309 } catch (FileNotFoundException e) { 310 /* Shouldn't happen as we check to see if the file exists */ 311 Log.w(TAG, "Error getting wallpaper", e); 312 } 313 return null; 314 } 315 } 316 317 public WallpaperInfo getWallpaperInfo() { 318 synchronized (mLock) { 319 if (mWallpaperConnection != null) { 320 return mWallpaperConnection.mInfo; 321 } 322 return null; 323 } 324 } 325 326 public ParcelFileDescriptor setWallpaper(String name) { 327 if (DEBUG) Log.v(TAG, "setWallpaper"); 328 329 checkPermission(android.Manifest.permission.SET_WALLPAPER); 330 synchronized (mLock) { 331 final long ident = Binder.clearCallingIdentity(); 332 try { 333 ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name); 334 if (pfd != null) { 335 // Bind the wallpaper to an ImageWallpaper 336 bindWallpaperComponentLocked(mImageWallpaperComponent); 337 saveSettingsLocked(); 338 } 339 return pfd; 340 } finally { 341 Binder.restoreCallingIdentity(ident); 342 } 343 } 344 } 345 346 ParcelFileDescriptor updateWallpaperBitmapLocked(String name) { 347 if (name == null) name = ""; 348 try { 349 ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE, 350 MODE_CREATE|MODE_READ_WRITE); 351 mName = name; 352 return fd; 353 } catch (FileNotFoundException e) { 354 Log.w(TAG, "Error setting wallpaper", e); 355 } 356 return null; 357 } 358 359 public void setWallpaperComponent(ComponentName name) { 360 if (DEBUG) Log.v(TAG, "setWallpaperComponent name=" + name); 361 checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); 362 synchronized (mLock) { 363 final long ident = Binder.clearCallingIdentity(); 364 try { 365 bindWallpaperComponentLocked(name); 366 } finally { 367 Binder.restoreCallingIdentity(ident); 368 } 369 } 370 } 371 372 void bindWallpaperComponentLocked(ComponentName componentName) { 373 if (DEBUG) Log.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName); 374 375 // Has the component changed? 376 if (mWallpaperConnection != null) { 377 if (mWallpaperComponent == null) { 378 if (componentName == null) { 379 if (DEBUG) Log.v(TAG, "bindWallpaperComponentLocked: still using default"); 380 // Still using default wallpaper. 381 return; 382 } 383 } else if (mWallpaperComponent.equals(componentName)) { 384 // Changing to same wallpaper. 385 if (DEBUG) Log.v(TAG, "same wallpaper"); 386 return; 387 } 388 } 389 390 try { 391 if (componentName == null) { 392 String defaultComponent = 393 mContext.getString(com.android.internal.R.string.default_wallpaper_component); 394 if (defaultComponent != null) { 395 // See if there is a default wallpaper component specified 396 componentName = ComponentName.unflattenFromString(defaultComponent); 397 if (DEBUG) Log.v(TAG, "Use default component walpaper:" + componentName); 398 } 399 if (componentName == null) { 400 // Fall back to static image wallpaper 401 componentName = mImageWallpaperComponent; 402 //clearWallpaperComponentLocked(); 403 //return; 404 if (DEBUG) Log.v(TAG, "Using image wallpaper"); 405 } 406 } 407 ServiceInfo si = mContext.getPackageManager().getServiceInfo(componentName, 408 PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS); 409 if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) { 410 throw new SecurityException("Selected service does not require " 411 + android.Manifest.permission.BIND_WALLPAPER 412 + ": " + componentName); 413 } 414 415 WallpaperInfo wi = null; 416 417 Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE); 418 if (componentName != null && !componentName.equals(mImageWallpaperComponent)) { 419 // Make sure the selected service is actually a wallpaper service. 420 List<ResolveInfo> ris = mContext.getPackageManager() 421 .queryIntentServices(intent, PackageManager.GET_META_DATA); 422 for (int i=0; i<ris.size(); i++) { 423 ServiceInfo rsi = ris.get(i).serviceInfo; 424 if (rsi.name.equals(si.name) && 425 rsi.packageName.equals(si.packageName)) { 426 try { 427 wi = new WallpaperInfo(mContext, ris.get(i)); 428 } catch (XmlPullParserException e) { 429 throw new IllegalArgumentException(e); 430 } catch (IOException e) { 431 throw new IllegalArgumentException(e); 432 } 433 break; 434 } 435 } 436 if (wi == null) { 437 throw new SecurityException("Selected service is not a wallpaper: " 438 + componentName); 439 } 440 } 441 442 // Bind the service! 443 if (DEBUG) Log.v(TAG, "Binding to:" + componentName); 444 WallpaperConnection newConn = new WallpaperConnection(wi); 445 intent.setComponent(componentName); 446 intent.putExtra(Intent.EXTRA_CLIENT_LABEL, 447 com.android.internal.R.string.wallpaper_binding_label); 448 intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity( 449 mContext, 0, 450 Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER), 451 mContext.getText(com.android.internal.R.string.chooser_wallpaper)), 452 0)); 453 if (!mContext.bindService(intent, newConn, 454 Context.BIND_AUTO_CREATE)) { 455 throw new IllegalArgumentException("Unable to bind service: " 456 + componentName); 457 } 458 459 clearWallpaperComponentLocked(); 460 mWallpaperComponent = componentName; 461 mWallpaperConnection = newConn; 462 mLastDiedTime = SystemClock.uptimeMillis(); 463 try { 464 if (DEBUG) Log.v(TAG, "Adding window token: " + newConn.mToken); 465 mIWindowManager.addWindowToken(newConn.mToken, 466 WindowManager.LayoutParams.TYPE_WALLPAPER); 467 } catch (RemoteException e) { 468 } 469 470 } catch (PackageManager.NameNotFoundException e) { 471 throw new IllegalArgumentException("Unknown component " + componentName); 472 } 473 } 474 475 void clearWallpaperComponentLocked() { 476 mWallpaperComponent = null; 477 if (mWallpaperConnection != null) { 478 if (mWallpaperConnection.mEngine != null) { 479 try { 480 mWallpaperConnection.mEngine.destroy(); 481 } catch (RemoteException e) { 482 } 483 } 484 mContext.unbindService(mWallpaperConnection); 485 try { 486 if (DEBUG) Log.v(TAG, "Removing window token: " 487 + mWallpaperConnection.mToken); 488 mIWindowManager.removeWindowToken(mWallpaperConnection.mToken); 489 } catch (RemoteException e) { 490 } 491 mWallpaperConnection = null; 492 } 493 } 494 495 void attachServiceLocked(WallpaperConnection conn) { 496 try { 497 conn.mService.attach(conn, conn.mToken, 498 WindowManager.LayoutParams.TYPE_WALLPAPER, false, 499 mWidth, mHeight); 500 } catch (RemoteException e) { 501 Log.w(TAG, "Failed attaching wallpaper; clearing", e); 502 bindWallpaperComponentLocked(null); 503 } 504 } 505 506 private void notifyCallbacksLocked() { 507 final int n = mCallbacks.beginBroadcast(); 508 for (int i = 0; i < n; i++) { 509 try { 510 mCallbacks.getBroadcastItem(i).onWallpaperChanged(); 511 } catch (RemoteException e) { 512 513 // The RemoteCallbackList will take care of removing 514 // the dead object for us. 515 } 516 } 517 mCallbacks.finishBroadcast(); 518 final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED); 519 mContext.sendBroadcast(intent); 520 } 521 522 private void checkPermission(String permission) { 523 if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) { 524 throw new SecurityException("Access denied to process: " + Binder.getCallingPid() 525 + ", must have permission " + permission); 526 } 527 } 528 529 private static JournaledFile makeJournaledFile() { 530 final String base = "/data/system/wallpaper_info.xml"; 531 return new JournaledFile(new File(base), new File(base + ".tmp")); 532 } 533 534 private void saveSettingsLocked() { 535 JournaledFile journal = makeJournaledFile(); 536 FileOutputStream stream = null; 537 try { 538 stream = new FileOutputStream(journal.chooseForWrite(), false); 539 XmlSerializer out = new FastXmlSerializer(); 540 out.setOutput(stream, "utf-8"); 541 out.startDocument(null, true); 542 543 out.startTag(null, "wp"); 544 out.attribute(null, "width", Integer.toString(mWidth)); 545 out.attribute(null, "height", Integer.toString(mHeight)); 546 out.attribute(null, "name", mName); 547 if (mWallpaperComponent != null) { 548 out.attribute(null, "component", 549 mWallpaperComponent.flattenToShortString()); 550 } 551 out.endTag(null, "wp"); 552 553 out.endDocument(); 554 stream.close(); 555 journal.commit(); 556 } catch (IOException e) { 557 try { 558 if (stream != null) { 559 stream.close(); 560 } 561 } catch (IOException ex) { 562 // Ignore 563 } 564 journal.rollback(); 565 } 566 } 567 568 private void loadSettingsLocked() { 569 if (DEBUG) Log.v(TAG, "loadSettingsLocked"); 570 571 JournaledFile journal = makeJournaledFile(); 572 FileInputStream stream = null; 573 File file = journal.chooseForRead(); 574 boolean success = false; 575 try { 576 stream = new FileInputStream(file); 577 XmlPullParser parser = Xml.newPullParser(); 578 parser.setInput(stream, null); 579 580 int type; 581 do { 582 type = parser.next(); 583 if (type == XmlPullParser.START_TAG) { 584 String tag = parser.getName(); 585 if ("wp".equals(tag)) { 586 mWidth = Integer.parseInt(parser.getAttributeValue(null, "width")); 587 mHeight = Integer.parseInt(parser.getAttributeValue(null, "height")); 588 mName = parser.getAttributeValue(null, "name"); 589 String comp = parser.getAttributeValue(null, "component"); 590 mNextWallpaperComponent = comp != null 591 ? ComponentName.unflattenFromString(comp) 592 : null; 593 594 if (DEBUG) { 595 Log.v(TAG, "mWidth:" + mWidth); 596 Log.v(TAG, "mHeight:" + mHeight); 597 Log.v(TAG, "mName:" + mName); 598 Log.v(TAG, "mNextWallpaperComponent:" + mNextWallpaperComponent); 599 } 600 } 601 } 602 } while (type != XmlPullParser.END_DOCUMENT); 603 success = true; 604 } catch (NullPointerException e) { 605 Log.w(TAG, "failed parsing " + file + " " + e); 606 } catch (NumberFormatException e) { 607 Log.w(TAG, "failed parsing " + file + " " + e); 608 } catch (XmlPullParserException e) { 609 Log.w(TAG, "failed parsing " + file + " " + e); 610 } catch (IOException e) { 611 Log.w(TAG, "failed parsing " + file + " " + e); 612 } catch (IndexOutOfBoundsException e) { 613 Log.w(TAG, "failed parsing " + file + " " + e); 614 } 615 try { 616 if (stream != null) { 617 stream.close(); 618 } 619 } catch (IOException e) { 620 // Ignore 621 } 622 623 if (!success) { 624 mWidth = -1; 625 mHeight = -1; 626 mName = ""; 627 } 628 } 629 630 void settingsRestored() { 631 if (DEBUG) Log.v(TAG, "settingsRestored"); 632 633 boolean success = false; 634 synchronized (mLock) { 635 loadSettingsLocked(); 636 if (mNextWallpaperComponent != null && 637 !mNextWallpaperComponent.equals(mImageWallpaperComponent)) { 638 // We can't restore live wallpapers, so just go with the default 639 bindWallpaperComponentLocked(null); 640 success = true; 641 } else { 642 // If there's a wallpaper name, we use that. If that can't be loaded, then we 643 // use the default. 644 if ("".equals(mName)) { 645 if (DEBUG) Log.v(TAG, "settingsRestored: name is empty"); 646 success = true; 647 } else { 648 if (DEBUG) Log.v(TAG, "settingsRestored: attempting to restore named resource"); 649 success = restoreNamedResourceLocked(); 650 } 651 if (DEBUG) Log.v(TAG, "settingsRestored: success=" + success); 652 if (success) { 653 bindWallpaperComponentLocked(mImageWallpaperComponent); 654 } 655 } 656 } 657 658 if (!success) { 659 Log.e(TAG, "Failed to restore wallpaper: '" + mName + "'"); 660 mName = ""; 661 WALLPAPER_FILE.delete(); 662 } 663 saveSettingsLocked(); 664 } 665 666 boolean restoreNamedResourceLocked() { 667 if (mName.length() > 4 && "res:".equals(mName.substring(0, 4))) { 668 String resName = mName.substring(4); 669 670 String pkg = null; 671 int colon = resName.indexOf(':'); 672 if (colon > 0) { 673 pkg = resName.substring(0, colon); 674 } 675 676 String ident = null; 677 int slash = resName.lastIndexOf('/'); 678 if (slash > 0) { 679 ident = resName.substring(slash+1); 680 } 681 682 String type = null; 683 if (colon > 0 && slash > 0 && (slash-colon) > 1) { 684 type = resName.substring(colon+1, slash); 685 } 686 687 if (pkg != null && ident != null && type != null) { 688 int resId = -1; 689 InputStream res = null; 690 FileOutputStream fos = null; 691 try { 692 Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED); 693 Resources r = c.getResources(); 694 resId = r.getIdentifier(resName, null, null); 695 if (resId == 0) { 696 Log.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type 697 + " ident=" + ident); 698 return false; 699 } 700 701 res = r.openRawResource(resId); 702 fos = new FileOutputStream(WALLPAPER_FILE); 703 704 byte[] buffer = new byte[32768]; 705 int amt; 706 while ((amt=res.read(buffer)) > 0) { 707 fos.write(buffer, 0, amt); 708 } 709 // mWallpaperObserver will notice the close and send the change broadcast 710 711 Log.v(TAG, "Restored wallpaper: " + resName); 712 return true; 713 } catch (NameNotFoundException e) { 714 Log.e(TAG, "Package name " + pkg + " not found"); 715 } catch (Resources.NotFoundException e) { 716 Log.e(TAG, "Resource not found: " + resId); 717 } catch (IOException e) { 718 Log.e(TAG, "IOException while restoring wallpaper ", e); 719 } finally { 720 if (res != null) { 721 try { 722 res.close(); 723 } catch (IOException ex) {} 724 } 725 if (fos != null) { 726 try { 727 fos.close(); 728 } catch (IOException ex) {} 729 } 730 } 731 } 732 } 733 return false; 734 } 735 736 @Override 737 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 738 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 739 != PackageManager.PERMISSION_GRANTED) { 740 741 pw.println("Permission Denial: can't dump wallpaper service from from pid=" 742 + Binder.getCallingPid() 743 + ", uid=" + Binder.getCallingUid()); 744 return; 745 } 746 747 synchronized (mLock) { 748 pw.println("Current Wallpaper Service state:"); 749 pw.print(" mWidth="); pw.print(mWidth); 750 pw.print(" mHeight="); pw.println(mHeight); 751 pw.print(" mName="); pw.println(mName); 752 pw.print(" mWallpaperComponent="); pw.println(mWallpaperComponent); 753 if (mWallpaperConnection != null) { 754 WallpaperConnection conn = mWallpaperConnection; 755 pw.print(" Wallpaper connection "); 756 pw.print(conn); pw.println(":"); 757 pw.print(" mInfo.component="); pw.println(conn.mInfo.getComponent()); 758 pw.print(" mToken="); pw.println(conn.mToken); 759 pw.print(" mService="); pw.println(conn.mService); 760 pw.print(" mEngine="); pw.println(conn.mEngine); 761 pw.print(" mLastDiedTime="); 762 pw.println(mLastDiedTime - SystemClock.uptimeMillis()); 763 } 764 } 765 } 766} 767