diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-05 20:00:43 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-05 20:00:43 -0800 |
commit | f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2 (patch) | |
tree | 3a24d2250b24d928cd5b67936affc4f0ac3b599b | |
parent | 53b404521227d30353f0f2421458103dff903626 (diff) | |
download | frameworks_base-f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2.zip frameworks_base-f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2.tar.gz frameworks_base-f5b4b98fada53d91c4c2ebeb5a1d33ccc95c94d2.tar.bz2 |
auto import from //depot/cupcake/@136745
-rw-r--r-- | cmds/am/src/com/android/commands/am/Am.java | 48 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 29 | ||||
-rw-r--r-- | core/java/android/app/ActivityThread.java | 24 | ||||
-rw-r--r-- | core/java/android/app/ApplicationThreadNative.java | 18 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 5 | ||||
-rw-r--r-- | core/java/android/app/IApplicationThread.java | 2 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothA2dp.java | 12 | ||||
-rw-r--r-- | core/java/android/bluetooth/BluetoothHeadset.java | 14 | ||||
-rw-r--r-- | core/java/android/server/BluetoothDeviceService.java | 3 | ||||
-rw-r--r-- | core/java/android/view/GestureDetector.java | 5 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 50 |
11 files changed, 204 insertions, 6 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java index b86d40a..6d4b455 100644 --- a/cmds/am/src/com/android/commands/am/Am.java +++ b/cmds/am/src/com/android/commands/am/Am.java @@ -75,6 +75,8 @@ public class Am { runInstrument(); } else if (op.equals("broadcast")) { sendBroadcast(); + } else if (op.equals("profile")) { + runProfile(); } else { System.err.println("Error: Unknown command: " + op); showUsage(); @@ -423,6 +425,49 @@ public class Am { } } + private void runProfile() { + String profileFile = null; + boolean start = false; + + String process = nextArg(); + if (process == null) { + System.err.println("Error: No profile process supplied"); + showUsage(); + return; + } + + String cmd = nextArg(); + if ("start".equals(cmd)) { + start = true; + profileFile = nextArg(); + if (profileFile == null) { + System.err.println("Error: No profile file path supplied"); + showUsage(); + return; + } + } else if (!"stop".equals(cmd)) { + System.err.println("Error: Profile command " + cmd + " not valid"); + showUsage(); + return; + } + + try { + if (!mAm.profileControl(process, start, profileFile)) { + System.out.println("PROFILE FAILED on process " + process); + return; + } + } catch (IllegalArgumentException e) { + System.out.println("PROFILE FAILED: " + e.getMessage()); + return; + } catch (IllegalStateException e) { + System.out.println("PROFILE FAILED: " + e.getMessage()); + return; + } catch (RemoteException e) { + System.out.println("PROFILE FAILED: activity manager gone"); + return; + } + } + private String nextOption() { if (mNextArg >= mArgs.length) { return null; @@ -470,11 +515,12 @@ public class Am { } private void showUsage() { - System.err.println("usage: am [start|broadcast|instrument]"); + System.err.println("usage: am [start|broadcast|instrument|profile]"); System.err.println(" am start -D INTENT"); System.err.println(" am broadcast INTENT"); System.err.println(" am instrument [-r] [-e <ARG_NAME> <ARG_VALUE>] [-p <PROF_FILE>]"); System.err.println(" [-w] <COMPONENT> "); + System.err.println(" am profile <PROCESS> [start <PROF_FILE>|stop]"); System.err.println(""); System.err.println(" INTENT is described with:"); System.err.println(" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]"); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index f11dbec..53e6f34 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -979,6 +979,17 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case PROFILE_CONTROL_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + String process = data.readString(); + boolean start = data.readInt() != 0; + String path = data.readString(); + boolean res = profileControl(process, start, path); + reply.writeNoException(); + reply.writeInt(res ? 1 : 0); + return true; + } + case PEEK_SERVICE_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); Intent service = Intent.CREATOR.createFromParcel(data); @@ -2131,5 +2142,23 @@ class ActivityManagerProxy implements IActivityManager data.recycle(); return res; } + + public boolean profileControl(String process, boolean start, + String path) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeString(process); + data.writeInt(start ? 1 : 0); + data.writeString(path); + mRemote.transact(PROFILE_CONTROL_TRANSACTION, data, reply, 0); + reply.readException(); + boolean res = reply.readInt() != 0; + reply.recycle(); + data.recycle(); + return res; + } + private IBinder mRemote; } diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index bf5616e..f49005e 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1449,6 +1449,10 @@ public final class ActivityThread { } } + public void profilerControl(boolean start, String path) { + queueOrSendMessage(H.PROFILER_CONTROL, path, start ? 1 : 0); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { long nativeMax = Debug.getNativeHeapSize() / 1024; @@ -1641,6 +1645,7 @@ public final class ActivityThread { public static final int LOW_MEMORY = 124; public static final int ACTIVITY_CONFIGURATION_CHANGED = 125; public static final int RELAUNCH_ACTIVITY = 126; + public static final int PROFILER_CONTROL = 127; String codeToString(int code) { if (localLOGV) { switch (code) { @@ -1671,6 +1676,7 @@ public final class ActivityThread { case LOW_MEMORY: return "LOW_MEMORY"; case ACTIVITY_CONFIGURATION_CHANGED: return "ACTIVITY_CONFIGURATION_CHANGED"; case RELAUNCH_ACTIVITY: return "RELAUNCH_ACTIVITY"; + case PROFILER_CONTROL: return "PROFILER_CONTROL"; } } return "(unknown)"; @@ -1770,6 +1776,9 @@ public final class ActivityThread { case ACTIVITY_CONFIGURATION_CHANGED: handleActivityConfigurationChanged((IBinder)msg.obj); break; + case PROFILER_CONTROL: + handleProfilerControl(msg.arg1 != 0, (String)msg.obj); + break; } } } @@ -3432,6 +3441,21 @@ public final class ActivityThread { performConfigurationChanged(r.activity, mConfiguration); } + final void handleProfilerControl(boolean start, String path) { + if (start) { + File file = new File(path); + file.getParentFile().mkdirs(); + try { + Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); + } catch (RuntimeException e) { + Log.w(TAG, "Profiling failed on path " + path + + " -- can the process access this path?"); + } + } else { + Debug.stopMethodTracing(); + } + } + final void handleLowMemory() { ArrayList<ComponentCallbacks> callbacks = new ArrayList<ComponentCallbacks>(); diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index d2cf55a..bcc9302 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -322,6 +322,15 @@ public abstract class ApplicationThreadNative extends Binder requestPss(); return true; } + + case PROFILER_CONTROL_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + boolean start = data.readInt() != 0; + String path = data.readString(); + profilerControl(start, path); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -654,5 +663,14 @@ class ApplicationThreadProxy implements IApplicationThread { data.recycle(); } + public void profilerControl(boolean start, String path) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeInt(start ? 1 : 0); + data.writeString(path); + mRemote.transact(PROFILER_CONTROL_TRANSACTION, data, null, + IBinder.FLAG_ONEWAY); + data.recycle(); + } } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index cd3701f..2ac6160 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -221,6 +221,10 @@ public interface IActivityManager extends IInterface { // Get device configuration public ConfigurationInfo getDeviceConfigurationInfo() throws RemoteException; + // Turn on/off profiling in a particular process. + public boolean profileControl(String process, boolean start, + String path) throws RemoteException; + /* * Private non-Binder interfaces */ @@ -365,4 +369,5 @@ public interface IActivityManager extends IInterface { int GET_RUNNING_APP_PROCESSES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+82; int GET_DEVICE_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+83; int PEEK_SERVICE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+84; + int PROFILE_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+85; } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index 47476b5..9f3534b 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -86,6 +86,7 @@ public interface IApplicationThread extends IInterface { void scheduleLowMemory() throws RemoteException; void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException; void requestPss() throws RemoteException; + void profilerControl(boolean start, String path) throws RemoteException; String descriptor = "android.app.IApplicationThread"; @@ -115,4 +116,5 @@ public interface IApplicationThread extends IInterface { int SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24; int SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25; int REQUEST_PSS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26; + int PROFILER_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27; } diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java index b0b0154..2ea45d5 100644 --- a/core/java/android/bluetooth/BluetoothA2dp.java +++ b/core/java/android/bluetooth/BluetoothA2dp.java @@ -49,6 +49,7 @@ import java.util.List; */ public class BluetoothA2dp { private static final String TAG = "BluetoothA2dp"; + private static final boolean DBG = false; /** int extra for SINK_STATE_CHANGED_ACTION */ public static final String SINK_STATE = @@ -103,6 +104,7 @@ public class BluetoothA2dp { * @hide */ public int connectSink(String address) { + if (DBG) log("connectSink(" + address + ")"); try { return mService.connectSink(address); } catch (RemoteException e) { @@ -119,6 +121,7 @@ public class BluetoothA2dp { * @hide */ public int disconnectSink(String address) { + if (DBG) log("disconnectSink(" + address + ")"); try { return mService.disconnectSink(address); } catch (RemoteException e) { @@ -133,6 +136,7 @@ public class BluetoothA2dp { * @hide */ public boolean isSinkConnected(String address) { + if (DBG) log("isSinkConnected(" + address + ")"); int state = getSinkState(address); return state == STATE_CONNECTED || state == STATE_PLAYING; } @@ -142,6 +146,7 @@ public class BluetoothA2dp { * @hide */ public List<String> listConnectedSinks() { + if (DBG) log("listConnectedSinks()"); try { return mService.listConnectedSinks(); } catch (RemoteException e) { @@ -156,6 +161,7 @@ public class BluetoothA2dp { * @hide */ public int getSinkState(String address) { + if (DBG) log("getSinkState(" + address + ")"); try { return mService.getSinkState(address); } catch (RemoteException e) { @@ -177,6 +183,7 @@ public class BluetoothA2dp { * @return Result code, negative indicates an error */ public int setSinkPriority(String address, int priority) { + if (DBG) log("setSinkPriority(" + address + ", " + priority + ")"); try { return mService.setSinkPriority(address, priority); } catch (RemoteException e) { @@ -191,6 +198,7 @@ public class BluetoothA2dp { * @return non-negative priority, or negative error code on error. */ public int getSinkPriority(String address) { + if (DBG) log("getSinkPriority(" + address + ")"); try { return mService.getSinkPriority(address); } catch (RemoteException e) { @@ -244,4 +252,8 @@ public class BluetoothA2dp { return "<unknown state " + state + ">"; } } + + private static void log(String msg) { + Log.d(TAG, msg); + } } diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 34196bf..e23545b 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -126,6 +126,7 @@ public class BluetoothHeadset { * are ok. */ public synchronized void close() { + if (DBG) log("close()"); if (mConnection != null) { mContext.unbindService(mConnection); mConnection = null; @@ -138,6 +139,7 @@ public class BluetoothHeadset { * object is currently not connected to the Headset service. */ public int getState() { + if (DBG) log("getState()"); if (mService != null) { try { return mService.getState(); @@ -156,6 +158,7 @@ public class BluetoothHeadset { * service. */ public String getHeadsetAddress() { + if (DBG) log("getHeadsetAddress()"); if (mService != null) { try { return mService.getHeadsetAddress(); @@ -180,6 +183,7 @@ public class BluetoothHeadset { * will be expected. */ public boolean connectHeadset(String address) { + if (DBG) log("connectHeadset(" + address + ")"); if (mService != null) { try { if (mService.connectHeadset(address)) { @@ -199,6 +203,7 @@ public class BluetoothHeadset { * if not currently connected to the headset service. */ public boolean isConnected(String address) { + if (DBG) log("isConnected(" + address + ")"); if (mService != null) { try { return mService.isConnected(address); @@ -216,6 +221,7 @@ public class BluetoothHeadset { * not currently connected to the Headset service. */ public boolean disconnectHeadset() { + if (DBG) log("disconnectHeadset()"); if (mService != null) { try { mService.disconnectHeadset(); @@ -235,6 +241,7 @@ public class BluetoothHeadset { * error. */ public boolean startVoiceRecognition() { + if (DBG) log("startVoiceRecognition()"); if (mService != null) { try { return mService.startVoiceRecognition(); @@ -252,6 +259,7 @@ public class BluetoothHeadset { * headset is not in voice recognition mode, or on error. */ public boolean stopVoiceRecognition() { + if (DBG) log("stopVoiceRecognition()"); if (mService != null) { try { return mService.stopVoiceRecognition(); @@ -282,6 +290,7 @@ public class BluetoothHeadset { * @return True if successful, false if there was some error. */ public boolean setPriority(String address, int priority) { + if (DBG) log("setPriority(" + address + ", " + priority + ")"); if (mService != null) { try { return mService.setPriority(address, priority); @@ -299,6 +308,7 @@ public class BluetoothHeadset { * @return non-negative priority, or negative error code on error. */ public int getPriority(String address) { + if (DBG) log("getPriority(" + address + ")"); if (mService != null) { try { return mService.getPriority(address); @@ -350,4 +360,8 @@ public class BluetoothHeadset { } } }; + + private static void log(String msg) { + Log.d(TAG, msg); + } } diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java index 950ff3a..87153cf 100644 --- a/core/java/android/server/BluetoothDeviceService.java +++ b/core/java/android/server/BluetoothDeviceService.java @@ -295,7 +295,8 @@ public class BluetoothDeviceService extends IBluetoothDevice.Stub { new ArrayList<String>(Arrays.asList( "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS - "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57"// Murata for Prius 2007 + "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57",// Murata for Prius 2007 + "00:0E:9F" // TEMIC SDS for Porsche )); public synchronized void loadBondState() { diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java index e0231a7..88ff3c5 100644 --- a/core/java/android/view/GestureDetector.java +++ b/core/java/android/view/GestureDetector.java @@ -499,13 +499,10 @@ public class GestureDetector { // Finally, give the up event of the double-tap handled |= mDoubleTapListener.onDoubleTapEvent(ev); mIsDoubleTapping = false; - break; } else if (mInLongPress) { mHandler.removeMessages(TAP); mInLongPress = false; - break; - } - if (mAlwaysInTapRegion) { + } else if (mAlwaysInTapRegion) { handled = mListener.onSingleTapUp(ev); } else { diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2ede783..9d720d1 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -11823,6 +11823,56 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + public boolean profileControl(String process, boolean start, + String path) throws RemoteException { + + synchronized (this) { + // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to + // its own permission. + if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException("Requires permission " + + android.Manifest.permission.SET_ACTIVITY_WATCHER); + } + + ProcessRecord proc = null; + try { + int pid = Integer.parseInt(process); + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(pid); + } + } catch (NumberFormatException e) { + } + + if (proc == null) { + HashMap<String, SparseArray<ProcessRecord>> all + = mProcessNames.getMap(); + SparseArray<ProcessRecord> procs = all.get(process); + if (procs != null && procs.size() > 0) { + proc = procs.valueAt(0); + } + } + + if (proc == null || proc.thread == null) { + throw new IllegalArgumentException("Unknown process: " + process); + } + + boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0")); + if (isSecure) { + if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) { + throw new SecurityException("Process not debuggable: " + proc); + } + } + + try { + proc.thread.profilerControl(start, path); + return true; + } catch (RemoteException e) { + throw new IllegalStateException("Process disappeared"); + } + } + } + /** In this method we try to acquire our lock to make sure that we have not deadlocked */ public void monitor() { synchronized (this) { } |