Merge "Fix for 4142219 Don't hard code platform-specific limitations (Jni/ Java)"
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index f8be136..b01dcd8 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -770,11 +770,7 @@
         value->computeValues(paint, textArray, start, count, end, flags);
 #endif
 
-#if DEBUG_GLYPHS
-        logGlyphs(value);
-#endif
-
-    doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(),
+        doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(),
             x, y, flags, paint);
     }
 
@@ -794,10 +790,6 @@
         value->computeValues(paint, textArray, start, count, contextCount, flags);
 #endif
 
-#if DEBUG_GLYPHS
-        logGlyphs(value);
-#endif
-
         doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(),
                 x, y, flags, paint);
     }
diff --git a/core/jni/android/graphics/TextLayout.h b/core/jni/android/graphics/TextLayout.h
index d197d04..9bb1b92 100644
--- a/core/jni/android/graphics/TextLayout.h
+++ b/core/jni/android/graphics/TextLayout.h
@@ -64,14 +64,6 @@
     kDirection_Mask = 0x1
 };
 
-static void logGlyphs(sp<TextLayoutCacheValue> value) {
-    if (value == NULL) return;
-    LOGD("Got glyphs - count=%d", value->getGlyphsCount());
-    for (size_t i = 0; i < value->getGlyphsCount(); i++) {
-        LOGD("      glyphs[%d]=%d", i, value->getGlyphs()[i]);
-    }
-}
-
 class TextLayout {
 public:
 
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 89440c9..f04c5eb5 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -554,6 +554,15 @@
 #endif
 }
 
+static void logGlyphs(HB_ShaperItem shaperItem) {
+    LOGD("Got glyphs - count=%d", shaperItem.num_glyphs);
+    for (size_t i = 0; i < shaperItem.num_glyphs; i++) {
+        LOGD("      glyphs[%d]=%d - offset.x=%f offset.y=%f", i, shaperItem.glyphs[i],
+                HBFixedToFloat(shaperItem.offsets[i].x),
+                HBFixedToFloat(shaperItem.offsets[i].y));
+    }
+}
+
 void TextLayoutCacheValue::computeRunValuesWithHarfbuzz(SkPaint* paint, const UChar* chars,
         size_t start, size_t count, size_t contextCount, bool isRTL,
         jfloat* outAdvances, jfloat* outTotalAdvance,
@@ -570,6 +579,8 @@
             shaperItem.kerning_applied);
     LOGD("         -- string= '%s'", String8(chars + start, count).string());
     LOGD("         -- isDevKernText=%d", paint->isDevKernText());
+
+    logGlyphs(shaperItem);
 #endif
 
     if (shaperItem.advances == NULL || shaperItem.num_glyphs == 0) {
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 80c79fd..fb5e5fe 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -472,9 +472,6 @@
     value = new TextLayoutCacheValue();
     value->computeValues(paint, text, 0, count, count, flags);
 #endif
-#if DEBUG_GLYPHS
-    logGlyphs(value);
-#endif
     const jchar* glyphArray = value->getGlyphs();
     int glyphCount = value->getGlyphsCount();
     int bytesCount = glyphCount * sizeof(jchar);
@@ -505,9 +502,6 @@
     value = new TextLayoutCacheValue();
     value->computeValues(paint, text, start, count, contextCount, flags);
 #endif
-#if DEBUG_GLYPHS
-    logGlyphs(value);
-#endif
     const jchar* glyphArray = value->getGlyphs();
     int glyphCount = value->getGlyphsCount();
     int bytesCount = glyphCount * sizeof(jchar);
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 12ab941..e615d93 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -419,7 +419,7 @@
     def.nVersion.s.nStep = 0;
     def.nPortIndex = portIndex;
     OMX_ERRORTYPE err = OMX_GetParameter(mHandle, OMX_IndexParamPortDefinition, &def);
-    if (err != OK)
+    if (err != OMX_ErrorNone)
     {
         LOGE("%s::%d:Error getting OMX_IndexParamPortDefinition", __FUNCTION__, __LINE__);
         return err;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 7764e35..ebadb5e 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2398,10 +2398,11 @@
         }
     }
 
+    final Object mScreenshotLock = new Object();
     ServiceConnection mScreenshotConnection = null;
     Runnable mScreenshotTimeout = null;
 
-    void finishScreenshot(ServiceConnection conn) {
+    void finishScreenshotLSS(ServiceConnection conn) {
         if (mScreenshotConnection == conn) {
             mContext.unbindService(conn);
             mScreenshotConnection = null;
@@ -2416,48 +2417,56 @@
         mHandler.post(new Runnable() {
             @Override
             public void run() {
-                if (mScreenshotConnection != null) {
-                    return;
-                }
-                ComponentName cn = new ComponentName("com.android.systemui",
-                        "com.android.systemui.screenshot.TakeScreenshotService");
-                Intent intent = new Intent();
-                intent.setComponent(cn);
-                ServiceConnection conn = new ServiceConnection() {
-                    @Override
-                    public void onServiceConnected(ComponentName name, IBinder service) {
-                        if (mScreenshotConnection != this) {
-                            return;
-                        }
-                        Messenger messenger = new Messenger(service);
-                        Message msg = Message.obtain(null, 1);
-                        final ServiceConnection myConn = this;
-                        Handler h = new Handler(mHandler.getLooper()) {
-                            @Override
-                            public void handleMessage(Message msg) {
-                                finishScreenshot(myConn);
-                            }
-                        };
-                        msg.replyTo = new Messenger(h);
-                        try {
-                            messenger.send(msg);
-                        } catch (RemoteException e) {
-                        }
+                synchronized (mScreenshotLock) {
+                    if (mScreenshotConnection != null) {
+                        return;
                     }
-                    @Override
-                    public void onServiceDisconnected(ComponentName name) {}
-                };
-                if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
-                    mScreenshotConnection = conn;
-                    mScreenshotTimeout = new Runnable() {
-                        @Override public void run() {
-                            if (mScreenshotConnection != null) {
-                                finishScreenshot(mScreenshotConnection);
+                    ComponentName cn = new ComponentName("com.android.systemui",
+                            "com.android.systemui.screenshot.TakeScreenshotService");
+                    Intent intent = new Intent();
+                    intent.setComponent(cn);
+                    ServiceConnection conn = new ServiceConnection() {
+                        @Override
+                        public void onServiceConnected(ComponentName name, IBinder service) {
+                            synchronized (mScreenshotLock) {
+                                if (mScreenshotConnection != this) {
+                                    return;
+                                }
+                                Messenger messenger = new Messenger(service);
+                                Message msg = Message.obtain(null, 1);
+                                final ServiceConnection myConn = this;
+                                Handler h = new Handler(mHandler.getLooper()) {
+                                    @Override
+                                    public void handleMessage(Message msg) {
+                                        synchronized (mScreenshotLock) {
+                                            finishScreenshotLSS(myConn);
+                                        }
+                                    }
+                                };
+                                msg.replyTo = new Messenger(h);
+                                try {
+                                    messenger.send(msg);
+                                } catch (RemoteException e) {
+                                }
                             }
                         }
-
+                        @Override
+                        public void onServiceDisconnected(ComponentName name) {}
                     };
-                    mHandler.postDelayed(mScreenshotTimeout, 10000);
+                    if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
+                        mScreenshotConnection = conn;
+                        mScreenshotTimeout = new Runnable() {
+                            @Override public void run() {
+                                synchronized (mScreenshotLock) {
+                                    if (mScreenshotConnection != null) {
+                                        finishScreenshotLSS(mScreenshotConnection);
+                                    }
+                                }
+                            }
+    
+                        };
+                        mHandler.postDelayed(mScreenshotTimeout, 10000);
+                    }
                 }
             }
         });
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 66c44b62..291ce75 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -572,8 +572,8 @@
      * string containing the provider's implementation class and values are a
      * ContentProviderRecord object containing the data about it.
      */
-    final HashMap<String, ContentProviderRecord> mProvidersByClass
-            = new HashMap<String, ContentProviderRecord>();
+    final HashMap<ComponentName, ContentProviderRecord> mProvidersByClass
+            = new HashMap<ComponentName, ContentProviderRecord>();
 
     /**
      * List of content providers who have clients waiting for them.  The
@@ -5438,10 +5438,11 @@
             for (int i=0; i<N; i++) {
                 ProviderInfo cpi =
                     (ProviderInfo)providers.get(i);
-                ContentProviderRecord cpr = mProvidersByClass.get(cpi.name);
+                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
+                ContentProviderRecord cpr = mProvidersByClass.get(comp);
                 if (cpr == null) {
                     cpr = new ContentProviderRecord(cpi, app.info);
-                    mProvidersByClass.put(cpi.name, cpr);
+                    mProvidersByClass.put(comp, cpr);
                 }
                 app.pubProviders.put(cpi.name, cpr);
                 app.addPackage(cpi.applicationInfo.packageName);
@@ -5606,8 +5607,9 @@
                     throw new IllegalArgumentException(
                             "Attempt to launch content provider before system ready");
                 }
-                
-                cpr = mProvidersByClass.get(cpi.name);
+
+                ComponentName comp = new ComponentName(cpi.packageName, cpi.name);
+                cpr = mProvidersByClass.get(comp);
                 final boolean firstClass = cpr == null;
                 if (firstClass) {
                     try {
@@ -5689,7 +5691,7 @@
                 // Make sure the provider is published (the same provider class
                 // may be published under multiple names).
                 if (firstClass) {
-                    mProvidersByClass.put(cpi.name, cpr);
+                    mProvidersByClass.put(comp, cpr);
                 }
                 mProvidersByName.put(name, cpr);
 
@@ -5769,7 +5771,8 @@
                         " when removing content provider " + name);
             }
             //update content provider record entry info
-            ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
+            ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
+            ContentProviderRecord localCpr = mProvidersByClass.get(comp);
             if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by "
                     + r.info.processName + " from process "
                     + localCpr.appInfo.processName);
@@ -5801,7 +5804,8 @@
             }
 
             //update content provider record entry info
-            ContentProviderRecord localCpr = mProvidersByClass.get(cpr.info.name);
+            ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name);
+            ContentProviderRecord localCpr = mProvidersByClass.get(comp);
             localCpr.externals--;
             if (localCpr.externals < 0) {
                 Slog.e(TAG, "Externals < 0 for content provider " + localCpr);
@@ -5835,7 +5839,8 @@
                 }
                 ContentProviderRecord dst = r.pubProviders.get(src.info.name);
                 if (dst != null) {
-                    mProvidersByClass.put(dst.info.name, dst);
+                    ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name);
+                    mProvidersByClass.put(comp, dst);
                     String names[] = dst.info.authority.split(";");
                     for (int j = 0; j < names.length; j++) {
                         mProvidersByName.put(names[j], dst);
@@ -7607,15 +7612,15 @@
                 pw.println("    i[ntents]: pending intent state");
                 pw.println("    p[rocesses]: process state");
                 pw.println("    o[om]: out of memory management");
-                pw.println("    prov[iders]: content provider state");
-                pw.println("    s[ervices]: service state");
+                pw.println("    prov[iders] [COMP_SPEC ...]: content provider state");
+                pw.println("    s[ervices] [COMP_SPEC ...]: service state");
                 pw.println("    service [COMP_SPEC]: service client-side state");
+                pw.println("    all: dump all activities");
+                pw.println("    top: dump the top activity");
                 pw.println("  cmd may also be a COMP_SPEC to dump activities.");
-                pw.println("  COMP_SPEC may also be a component name (com.foo/.myApp),");
-                pw.println("    a partial substring in a component name, an");
-                pw.println("    ActivityRecord hex object identifier, or");
-                pw.println("    \"all\" for all objects, or");
-                pw.println("    \"top\" for the top activity.");
+                pw.println("  COMP_SPEC may be a component name (com.foo/.myApp),");
+                pw.println("    a partial substring in a component name, a");
+                pw.println("    hex object identifier.");
                 pw.println("  -a: include all available server state.");
                 pw.println("  -c: include client state.");
                 return;
@@ -8166,9 +8171,89 @@
         }
     }
 
+    static class ItemMatcher {
+        ArrayList<ComponentName> components;
+        ArrayList<String> strings;
+        ArrayList<Integer> objects;
+        boolean all;
+        
+        ItemMatcher() {
+            all = true;
+        }
+
+        void build(String name) {
+            ComponentName componentName = ComponentName.unflattenFromString(name);
+            if (componentName != null) {
+                if (components == null) {
+                    components = new ArrayList<ComponentName>();
+                }
+                components.add(componentName);
+                all = false;
+            } else {
+                int objectId = 0;
+                // Not a '/' separated full component name; maybe an object ID?
+                try {
+                    objectId = Integer.parseInt(name, 16);
+                    if (objects == null) {
+                        objects = new ArrayList<Integer>();
+                    }
+                    objects.add(objectId);
+                    all = false;
+                } catch (RuntimeException e) {
+                    // Not an integer; just do string match.
+                    if (strings == null) {
+                        strings = new ArrayList<String>();
+                    }
+                    strings.add(name);
+                    all = false;
+                }
+            }
+        }
+
+        int build(String[] args, int opti) {
+            for (; opti<args.length; opti++) {
+                String name = args[opti];
+                if ("--".equals(name)) {
+                    return opti+1;
+                }
+                build(name);
+            }
+            return opti;
+        }
+
+        boolean match(Object object, ComponentName comp) {
+            if (all) {
+                return true;
+            }
+            if (components != null) {
+                for (int i=0; i<components.size(); i++) {
+                    if (components.get(i).equals(comp)) {
+                        return true;
+                    }
+                }
+            }
+            if (objects != null) {
+                for (int i=0; i<objects.size(); i++) {
+                    if (System.identityHashCode(object) == objects.get(i)) {
+                        return true;
+                    }
+                }
+            }
+            if (strings != null) {
+                String flat = comp.flattenToString();
+                for (int i=0; i<strings.size(); i++) {
+                    if (flat.contains(strings.get(i))) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+
     /**
      * There are three things that cmd can be:
-     *  - a flattened component name that matched an existing activity
+     *  - a flattened component name that matches an existing activity
      *  - the cmd arg isn't the flattened component name of an existing activity:
      *    dump all activity whose component contains the cmd as a substring
      *  - A hex number of the ActivityRecord object instance.
@@ -8191,29 +8276,12 @@
                 }
             }
         } else {
-            ComponentName componentName = ComponentName.unflattenFromString(name);
-            int objectId = 0;
-            if (componentName == null) {
-                // Not a '/' separated full component name; maybe an object ID?
-                try {
-                    objectId = Integer.parseInt(name, 16);
-                    name = null;
-                    componentName = null;
-                } catch (RuntimeException e) {
-                }
-            }
+            ItemMatcher matcher = new ItemMatcher();
+            matcher.build(name);
 
             synchronized (this) {
                 for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
-                    if (componentName != null) {
-                        if (r1.intent.getComponent().equals(componentName)) {
-                            activities.add(r1);
-                        }
-                    } else if (name != null) {
-                        if (r1.intent.getComponent().flattenToString().contains(name)) {
-                            activities.add(r1);
-                        }
-                    } else if (System.identityHashCode(r1) == objectId) {
+                    if (matcher.match(r1, r1.intent.getComponent())) {
                         activities.add(r1);
                     }
                 }
@@ -8404,6 +8472,9 @@
             int opti, boolean dumpAll, boolean dumpClient) {
         boolean needSep = false;
 
+        ItemMatcher matcher = new ItemMatcher();
+        matcher.build(args, opti);
+
         pw.println("ACTIVITY MANAGER SERVICES (dumpsys activity services)");
         if (mServices.size() > 0) {
             pw.println("  Active services:");
@@ -8412,6 +8483,9 @@
             needSep = false;
             while (it.hasNext()) {
                 ServiceRecord r = it.next();
+                if (!matcher.match(r, r.name)) {
+                    continue;
+                }
                 if (needSep) {
                     pw.println();
                 }
@@ -8457,6 +8531,9 @@
             pw.println("  Pending services:");
             for (int i=0; i<mPendingServices.size(); i++) {
                 ServiceRecord r = mPendingServices.get(i);
+                if (!matcher.match(r, r.name)) {
+                    continue;
+                }
                 pw.print("  * Pending "); pw.println(r);
                 r.dump(pw, "    ");
             }
@@ -8468,6 +8545,9 @@
             pw.println("  Restarting services:");
             for (int i=0; i<mRestartingServices.size(); i++) {
                 ServiceRecord r = mRestartingServices.get(i);
+                if (!matcher.match(r, r.name)) {
+                    continue;
+                }
                 pw.print("  * Restarting "); pw.println(r);
                 r.dump(pw, "    ");
             }
@@ -8479,6 +8559,9 @@
             pw.println("  Stopping services:");
             for (int i=0; i<mStoppingServices.size(); i++) {
                 ServiceRecord r = mStoppingServices.get(i);
+                if (!matcher.match(r, r.name)) {
+                    continue;
+                }
                 pw.print("  * Stopping "); pw.println(r);
                 r.dump(pw, "    ");
             }
@@ -8494,8 +8577,12 @@
                 while (it.hasNext()) {
                     ArrayList<ConnectionRecord> r = it.next();
                     for (int i=0; i<r.size(); i++) {
-                        pw.print("  * "); pw.println(r.get(i));
-                        r.get(i).dump(pw, "    ");
+                        ConnectionRecord cr = r.get(i);
+                        if (!matcher.match(cr.binding.service, cr.binding.service.name)) {
+                            continue;
+                        }
+                        pw.print("  * "); pw.println(cr);
+                        cr.dump(pw, "    ");
                     }
                 }
                 needSep = true;
@@ -8509,20 +8596,34 @@
             int opti, boolean dumpAll) {
         boolean needSep = false;
 
+        ItemMatcher matcher = new ItemMatcher();
+        matcher.build(args, opti);
+
         pw.println("ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)");
         if (mProvidersByClass.size() > 0) {
             if (needSep) pw.println(" ");
             pw.println("  Published content providers (by class):");
-            Iterator<Map.Entry<String, ContentProviderRecord>> it
+            Iterator<Map.Entry<ComponentName, ContentProviderRecord>> it
                     = mProvidersByClass.entrySet().iterator();
             while (it.hasNext()) {
-                Map.Entry<String, ContentProviderRecord> e = it.next();
+                Map.Entry<ComponentName, ContentProviderRecord> e = it.next();
                 ContentProviderRecord r = e.getValue();
+                ComponentName comp = e.getKey();
+                String cls = comp.getClassName();
+                int end = cls.lastIndexOf('.');
+                if (end > 0 && end < (cls.length()-2)) {
+                    cls = cls.substring(end+1);
+                }
+                if (!matcher.match(r, comp)) {
+                    continue;
+                }
+                pw.print("  * "); pw.print(cls); pw.print(" (");
+                        pw.print(comp.flattenToShortString()); pw.print(")");
                 if (dumpAll) {
-                    pw.print("  * "); pw.println(r);
-                    r.dump(pw, "    ");
+                    pw.println();
+                    r.dump(pw, "      ");
                 } else {
-                    pw.print("  * "); pw.print(r.name.toShortString());
+                    pw.print("  * "); pw.print(e.getKey().flattenToShortString());
                     if (r.app != null) {
                         pw.println(":");
                         pw.print("      "); pw.println(r.app);
@@ -8543,6 +8644,9 @@
                 while (it.hasNext()) {
                     Map.Entry<String, ContentProviderRecord> e = it.next();
                     ContentProviderRecord r = e.getValue();
+                    if (!matcher.match(r, r.name)) {
+                        continue;
+                    }
                     pw.print("  "); pw.print(e.getKey()); pw.print(": ");
                             pw.println(r);
                 }