• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
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 
17 package com.android.ide.eclipse.adt.internal.project;
18 
19 import com.android.ddmlib.AndroidDebugBridge;
20 import com.android.ddmlib.IDevice;
21 import com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener;
22 import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
23 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor;
24 import com.android.ide.eclipse.adt.internal.resources.manager.ResourceMonitor.IProjectListener;
25 
26 import org.eclipse.core.resources.IProject;
27 
28 import java.util.ArrayList;
29 
30 /**
31  * Registers which apk was installed on which device.
32  * <p/>
33  * The goal of this class is to remember the installation of APKs on devices, and provide
34  * information about whether a new APK should be installed on a device prior to running the
35  * application from a launch configuration.
36  * <p/>
37  * The manager uses {@link IProject} and {@link IDevice} to identify the target device and the
38  * (project generating the) APK. This ensures that disconnected and reconnected devices will
39  * always receive new APKs (since the APK could be uninstalled manually).
40  * <p/>
41  * Manually uninstalling an APK from a connected device will still be a problem, but this should
42  * be a limited use case.
43  * <p/>
44  * This is a singleton. To get the instance, use {@link #getInstance()}
45  */
46 public class ApkInstallManager implements IDeviceChangeListener, IDebugBridgeChangeListener,
47         IProjectListener {
48 
49     private final static ApkInstallManager sThis = new ApkInstallManager();
50 
51     /**
52      * Internal struct to associate a project and a device.
53      */
54     private static class ApkInstall {
ApkInstall(IProject project, IDevice device)55         public ApkInstall(IProject project, IDevice device) {
56             this.project = project;
57             this.device = device;
58         }
59         IProject project;
60         IDevice device;
61     }
62 
63     private final ArrayList<ApkInstall> mInstallList = new ArrayList<ApkInstall>();
64 
getInstance()65     public static ApkInstallManager getInstance() {
66         return sThis;
67     }
68 
69     /**
70      * Registers an installation of <var>project</var> onto <var>device</var>
71      * @param project The project that was installed.
72      * @param device The device that received the installation.
73      */
registerInstallation(IProject project, IDevice device)74     public void registerInstallation(IProject project, IDevice device) {
75         synchronized (mInstallList) {
76             mInstallList.add(new ApkInstall(project, device));
77         }
78     }
79 
80     /**
81      * Returns whether a <var>project</var> was installed on the <var>device</var>.
82      * @param project the project that may have been installed.
83      * @param device the device that may have received the installation.
84      * @return
85      */
isApplicationInstalled(IProject project, IDevice device)86     public boolean isApplicationInstalled(IProject project, IDevice device) {
87         synchronized (mInstallList) {
88             for (ApkInstall install : mInstallList) {
89                 if (project == install.project && device == install.device) {
90                     return true;
91                 }
92             }
93         }
94         return false;
95     }
96 
97     /**
98      * Resets registered installations for a specific {@link IProject}.
99      * <p/>This ensures that {@link #isApplicationInstalled(IProject, IDevice)} will always return
100      * <code>null</code> for this specified project, for any device.
101      * @param project the project for which to reset all installations.
102      */
resetInstallationFor(IProject project)103     public void resetInstallationFor(IProject project) {
104         synchronized (mInstallList) {
105             for (int i = 0 ; i < mInstallList.size() ;) {
106                 ApkInstall install = mInstallList.get(i);
107                 if (install.project == project) {
108                     mInstallList.remove(i);
109                 } else {
110                     i++;
111                 }
112             }
113         }
114     }
115 
ApkInstallManager()116     private ApkInstallManager() {
117         AndroidDebugBridge.addDeviceChangeListener(this);
118         AndroidDebugBridge.addDebugBridgeChangeListener(this);
119         ResourceMonitor.getMonitor().addProjectListener(this);
120     }
121 
122     /*
123      * Responds to a bridge change by clearing the full installation list.
124      * (non-Javadoc)
125      * @see com.android.ddmlib.AndroidDebugBridge.IDebugBridgeChangeListener#bridgeChanged(com.android.ddmlib.AndroidDebugBridge)
126      */
bridgeChanged(AndroidDebugBridge bridge)127     public void bridgeChanged(AndroidDebugBridge bridge) {
128         // the bridge changed, there is no way to know which IDevice will be which.
129         // We reset everything
130         synchronized (mInstallList) {
131             mInstallList.clear();
132         }
133     }
134 
135     /*
136      * Responds to a device being disconnected by removing all installations related to this device.
137      * (non-Javadoc)
138      * @see com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener#deviceDisconnected(com.android.ddmlib.Device)
139      */
deviceDisconnected(IDevice device)140     public void deviceDisconnected(IDevice device) {
141         synchronized (mInstallList) {
142             for (int i = 0 ; i < mInstallList.size() ;) {
143                 ApkInstall install = mInstallList.get(i);
144                 if (install.device == device) {
145                     mInstallList.remove(i);
146                 } else {
147                     i++;
148                 }
149             }
150         }
151     }
152 
153     /*
154      * Responds to a close project by resetting all its installation.
155      * (non-Javadoc)
156      * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectClosed(org.eclipse.core.resources.IProject)
157      */
projectClosed(IProject project)158     public void projectClosed(IProject project) {
159         resetInstallationFor(project);
160     }
161 
162     /*
163      * Responds to a close project by resetting all its installation.
164      * (non-Javadoc)
165      * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectDeleted(org.eclipse.core.resources.IProject)
166      */
projectDeleted(IProject project)167     public void projectDeleted(IProject project) {
168         resetInstallationFor(project);
169     }
170 
171     /*
172      * Does nothing
173      * (non-Javadoc)
174      * @see com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener#deviceChanged(com.android.ddmlib.Device, int)
175      */
deviceChanged(IDevice device, int changeMask)176     public void deviceChanged(IDevice device, int changeMask) {
177         // nothing to do.
178     }
179 
180     /*
181      * Does nothing
182      * (non-Javadoc)
183      * @see com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener#deviceConnected(com.android.ddmlib.Device)
184      */
deviceConnected(IDevice device)185     public void deviceConnected(IDevice device) {
186         // nothing to do.
187     }
188 
189     /*
190      * Does nothing
191      * (non-Javadoc)
192      * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectOpened(org.eclipse.core.resources.IProject)
193      */
projectOpened(IProject project)194     public void projectOpened(IProject project) {
195         // nothing to do.
196     }
197 
198     /*
199      * Does nothing
200      * (non-Javadoc)
201      * @see com.android.ide.eclipse.editors.resources.manager.ResourceMonitor.IProjectListener#projectOpenedWithWorkspace(org.eclipse.core.resources.IProject)
202      */
projectOpenedWithWorkspace(IProject project)203     public void projectOpenedWithWorkspace(IProject project) {
204         // nothing to do.
205     }
206 }
207