Home | History | Annotate | Download | only in logic
      1 /*
      2 * Copyright (C) 2012 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 package com.motorola.studio.android.emulator.logic;
     17 
     18 import static com.motorola.studio.android.common.log.StudioLogger.error;
     19 import static com.motorola.studio.android.common.log.StudioLogger.info;
     20 
     21 import java.io.IOException;
     22 import java.util.Collection;
     23 import java.util.LinkedList;
     24 
     25 import org.eclipse.core.runtime.IProgressMonitor;
     26 import org.eclipse.core.runtime.IStatus;
     27 import org.eclipse.core.runtime.Status;
     28 import org.eclipse.core.runtime.jobs.IJobChangeListener;
     29 import org.eclipse.core.runtime.jobs.IJobManager;
     30 import org.eclipse.core.runtime.jobs.ISchedulingRule;
     31 import org.eclipse.core.runtime.jobs.Job;
     32 
     33 import com.motorola.studio.android.adt.DDMSFacade;
     34 import com.motorola.studio.android.adt.ISerialNumbered;
     35 import com.motorola.studio.android.common.exception.AndroidException;
     36 import com.motorola.studio.android.emulator.EmulatorPlugin;
     37 import com.motorola.studio.android.emulator.core.exception.InstanceStartException;
     38 import com.motorola.studio.android.emulator.core.exception.StartCancelledException;
     39 import com.motorola.studio.android.emulator.core.exception.StartTimeoutException;
     40 import com.motorola.studio.android.emulator.core.model.IAndroidEmulatorInstance;
     41 
     42 /**
     43  *  This class contains the logic to start the VNC server on the given Emulator.
     44  */
     45 public final class StartVncServerLogic implements IAndroidLogic
     46 {
     47     public static final String VNC_SERVER_JOB_PREFIX = "VNC Server - ";
     48 
     49     public static final Object VNC_SERVER_JOB_FAMILY = new Object();
     50 
     51     /**
     52      * Sequence of commands that must be executed on the emulator to start the VNC server
     53      */
     54     private final Collection<String> remoteCommands = new LinkedList<String>();
     55 
     56     /**
     57      * Collection of listeners for the job executing the VNC server.
     58      */
     59     private final Collection<IJobChangeListener> listeners = new LinkedList<IJobChangeListener>();
     60 
     61     /**
     62      * Executes the logic to start the vnc server.
     63      */
     64     public void execute(final IAndroidLogicInstance instance, int timeout,
     65             final IProgressMonitor monitor) throws InstanceStartException, StartTimeoutException,
     66             StartCancelledException, IOException
     67     {
     68         cancelCurrentVncServerJobs(instance);
     69 
     70         // Creates and starts a job that will keep running as long as the VNC server is up on that Emulator instance.
     71         // add listeners that will receive notifications about the Job life-cycle.
     72         VncServerJob vncServerJob = new VncServerJob(instance, getRemoteCommands());
     73         for (IJobChangeListener vncServerListener : listeners)
     74         {
     75             vncServerJob.addJobChangeListener(vncServerListener);
     76         }
     77         vncServerJob.schedule();
     78 
     79     }
     80 
     81     /**
     82      * Cancel any VncServerJob that is currently running the VNC server on the given emulator instance.
     83      * @param instance, the emulator instances where VNC server execution must be canceled.
     84      **/
     85     public static void cancelCurrentVncServerJobs(IAndroidEmulatorInstance instance)
     86     {
     87         // stop the previous VNC Server job for this instance if any...
     88         IJobManager manager = Job.getJobManager();
     89         Job[] allVncJobs = manager.find(StartVncServerLogic.VNC_SERVER_JOB_FAMILY);
     90         if (allVncJobs.length > 0)
     91         {
     92             for (Job job : allVncJobs)
     93             {
     94                 if (job.getName().equals(
     95                         StartVncServerLogic.VNC_SERVER_JOB_PREFIX + instance.getName()))
     96                 {
     97                     info("Cancel execution of the VNC Server on " + instance);
     98                     job.cancel();
     99                 }
    100             }
    101         }
    102     }
    103 
    104     /**
    105      * Add job listener to receive state-change notifications from the job that runs the VNC Server.
    106      * @param vncServerListener job listener that willl receive state change notifications from the VNC Serever job.
    107      */
    108     public void addVncServerJobListener(IJobChangeListener vncServerListener)
    109     {
    110         listeners.add(vncServerListener);
    111     }
    112 
    113     /**
    114      * Add a command to be executed in the process of starting the VNC Server on the Emulator.
    115      * @param remoteCommand
    116      */
    117     public void addRemoteCommand(String remoteCommand)
    118     {
    119         remoteCommands.add(remoteCommand);
    120     }
    121 
    122     /**
    123      * Get the list of commands to be executed on the Emulator in order to start the VNC Server.
    124      * @return the sequence of commands that must be executed on the Emulator to start the VNC Server.
    125      */
    126     public Collection<String> getRemoteCommands()
    127     {
    128         return remoteCommands;
    129     }
    130 
    131 }
    132 
    133 /**
    134  * Job that executes the VNC Server.
    135  * It will keep running as long as the VNC Server process is running on the Emulator.
    136  */
    137 class VncServerJob extends Job implements ISchedulingRule
    138 {
    139     private String serialNumber;
    140 
    141     /**
    142      * Sequence of commands that must be executed on the emulator to start the VNC server
    143      */
    144     private final Collection<String> remoteCommands;
    145 
    146     /**
    147      * Creates a new job to execute the VNC server on the given emulator instance.
    148      * @param instance, emulator instance where the VNC server will be started.
    149      * @param remoteCommands, sequence of commands that must be executed on the given emulator instance to start the VNC Server.
    150      * @throws InstanceStartException
    151      */
    152     public VncServerJob(IAndroidLogicInstance instance, Collection<String> remoteCommands)
    153             throws InstanceStartException
    154     {
    155         super(StartVncServerLogic.VNC_SERVER_JOB_PREFIX + instance.getName());
    156 
    157         this.serialNumber = ((ISerialNumbered) instance).getSerialNumber();
    158 
    159         try
    160         {
    161             AndroidLogicUtils.testDeviceStatus(serialNumber);
    162         }
    163         catch (AndroidException e)
    164         {
    165             throw new InstanceStartException(e.getMessage());
    166         }
    167 
    168         this.remoteCommands = remoteCommands;
    169         setSystem(true);
    170         setRule(this);
    171     }
    172 
    173     /**
    174      * @see org.eclipse.core.runtime.jobs.Job#run(IProgressMonitor)
    175      */
    176     @Override
    177     public IStatus run(IProgressMonitor monitor)
    178     {
    179         IStatus status = Status.OK_STATUS;
    180         try
    181         {
    182             info("Executing VNC Server on " + serialNumber);
    183             AndroidLogicUtils.testDeviceStatus(serialNumber);
    184             DDMSFacade.execRemoteApp(serialNumber, remoteCommands, monitor);
    185 
    186             if (monitor.isCanceled())
    187             {
    188                 status = Status.CANCEL_STATUS;
    189             }
    190         }
    191         catch (Exception e)
    192         {
    193             String errorMessage = "Error while trying to run the VNC server on " + serialNumber;
    194             error(errorMessage + " " + e.getMessage());
    195             status = new Status(IStatus.CANCEL, EmulatorPlugin.PLUGIN_ID, errorMessage, e);
    196         }
    197 
    198         info("Finished the execution of the VNC Server on " + serialNumber + " with status "
    199                 + status);
    200 
    201         return status;
    202     }
    203 
    204     /**
    205      * @see org.eclipse.core.runtime.jobs.Job#belongsTo(Object)
    206      */
    207     @Override
    208     public boolean belongsTo(Object family)
    209     {
    210         return StartVncServerLogic.VNC_SERVER_JOB_FAMILY.equals(family);
    211     }
    212 
    213     public boolean contains(ISchedulingRule rule)
    214     {
    215         boolean contains = false;
    216         if (rule instanceof VncServerJob)
    217         {
    218             VncServerJob otherVncServerJob = (VncServerJob) rule;
    219             contains = otherVncServerJob.serialNumber.equals(serialNumber);
    220         }
    221 
    222         return contains;
    223     }
    224 
    225     public boolean isConflicting(ISchedulingRule rule)
    226     {
    227         return contains(rule);
    228     }
    229 }
    230