Home | History | Annotate | Download | only in dreams
      1 package android.service.dreams;
      2 
      3 import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT;
      4 
      5 import java.io.FileDescriptor;
      6 import java.io.PrintWriter;
      7 
      8 import com.android.internal.view.IInputMethod;
      9 
     10 import android.content.ComponentName;
     11 import android.content.Context;
     12 import android.content.Intent;
     13 import android.content.ServiceConnection;
     14 import android.content.pm.PackageManager;
     15 import android.os.Binder;
     16 import android.os.IBinder;
     17 import android.os.RemoteException;
     18 import android.os.ServiceManager;
     19 import android.os.SystemClock;
     20 import android.provider.Settings;
     21 import android.util.Log;
     22 import android.util.Slog;
     23 import android.view.IWindowManager;
     24 import android.view.WindowManager;
     25 
     26 /**
     27  *
     28  * @hide
     29  *
     30  */
     31 
     32 public class DreamManagerService
     33         extends IDreamManager.Stub
     34         implements ServiceConnection
     35 {
     36     private static final boolean DEBUG = true;
     37     private static final String TAG = "DreamManagerService";
     38 
     39     final Object mLock = new Object[0];
     40 
     41     private Context mContext;
     42     private IWindowManager mIWindowManager;
     43 
     44     private ComponentName mCurrentDreamComponent;
     45     private IDreamService mCurrentDream;
     46     private Binder mCurrentDreamToken;
     47 
     48     public DreamManagerService(Context context) {
     49         if (DEBUG) Slog.v(TAG, "DreamManagerService startup");
     50         mContext = context;
     51         mIWindowManager = IWindowManager.Stub.asInterface(
     52                 ServiceManager.getService(Context.WINDOW_SERVICE));
     53     }
     54 
     55     private void checkPermission(String permission) {
     56         if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) {
     57             throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
     58                     + ", must have permission " + permission);
     59         }
     60     }
     61 
     62     // IDreamManager method
     63     public void dream() {
     64         ComponentName name = getDreamComponent();
     65         if (name != null) {
     66             synchronized (mLock) {
     67                 final long ident = Binder.clearCallingIdentity();
     68                 try {
     69                     bindDreamComponentL(name, false);
     70                 } finally {
     71                     Binder.restoreCallingIdentity(ident);
     72                 }
     73             }
     74         }
     75     }
     76 
     77     // IDreamManager method
     78     public void setDreamComponent(ComponentName name) {
     79         Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString());
     80     }
     81 
     82     // IDreamManager method
     83     public ComponentName getDreamComponent() {
     84         // TODO(dsandler) don't load this every time, watch the value
     85         String component = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENT);
     86         if (component == null) {
     87             component = mContext.getResources().getString(
     88                 com.android.internal.R.string.config_defaultDreamComponent);
     89         }
     90         if (component != null) {
     91             return ComponentName.unflattenFromString(component);
     92         } else {
     93             return null;
     94         }
     95     }
     96 
     97     // IDreamManager method
     98     public void testDream(ComponentName name) {
     99         if (DEBUG) Slog.v(TAG, "startDream name=" + name
    100                 + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
    101 //        checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
    102         synchronized (mLock) {
    103             final long ident = Binder.clearCallingIdentity();
    104             try {
    105                 bindDreamComponentL(name, true);
    106             } finally {
    107                 Binder.restoreCallingIdentity(ident);
    108             }
    109         }
    110     }
    111 
    112     // IDreamManager method
    113     public void awaken() {
    114         if (DEBUG) Slog.v(TAG, "awaken()");
    115         synchronized (mLock) {
    116             if (mCurrentDream != null) {
    117                 mContext.unbindService(this);
    118             }
    119         }
    120     }
    121 
    122     public void bindDreamComponentL(ComponentName componentName, boolean test) {
    123         if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName
    124                 + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
    125 
    126         Intent intent = new Intent(Intent.ACTION_MAIN)
    127             .setComponent(componentName)
    128             .addFlags(
    129                 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
    130                 )
    131             .putExtra("android.dreams.TEST", test);
    132 
    133         if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) {
    134             Slog.w(TAG, "unable to bind service: " + componentName);
    135             return;
    136         }
    137         mCurrentDreamComponent = componentName;
    138         mCurrentDreamToken = new Binder();
    139         try {
    140             if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurrentDreamToken
    141                     + " for window type: " + WindowManager.LayoutParams.TYPE_DREAM);
    142             mIWindowManager.addWindowToken(mCurrentDreamToken,
    143                     WindowManager.LayoutParams.TYPE_DREAM);
    144         } catch (RemoteException e) {
    145             Slog.w(TAG, "Unable to add window token. Proceed at your own risk.");
    146         }
    147 
    148     }
    149 
    150     @Override
    151     public void onServiceConnected(ComponentName name, IBinder service) {
    152         if (DEBUG) Slog.v(TAG, "connected to dream: " + name + " binder=" + service + " thread=" + Thread.currentThread().getId());
    153 
    154         mCurrentDream = IDreamService.Stub.asInterface(service);
    155         try {
    156             if (DEBUG) Slog.v(TAG, "attaching with token:" + mCurrentDreamToken);
    157             mCurrentDream.attach(mCurrentDreamToken);
    158         } catch (RemoteException ex) {
    159             Slog.w(TAG, "Unable to send window token to dream:" + ex);
    160         }
    161     }
    162 
    163     @Override
    164     public void onServiceDisconnected(ComponentName name) {
    165         if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream);
    166         mCurrentDream = null;
    167         mCurrentDreamToken = null;
    168     }
    169 
    170     @Override
    171     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
    172         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
    173 
    174         pw.println("Dreamland:");
    175         pw.print("  component="); pw.println(mCurrentDreamComponent);
    176         pw.print("  token="); pw.println(mCurrentDreamToken);
    177         pw.print("  dream="); pw.println(mCurrentDream);
    178     }
    179 
    180     public void systemReady() {
    181         if (DEBUG) Slog.v(TAG, "ready to dream!");
    182     }
    183 
    184 }
    185