Bug 1244722 - TabQueueHelper.canDrawOverlays(): Implement workaround for Android bug. r=ahunt a=ritu
☠☠ backed out by 3f2bc8700930 ☠ ☠
authorSebastian Kaspari <s.kaspari@gmail.com>
Wed, 30 Mar 2016 12:58:27 +0200
changeset 324068 5b3bc1699878212f1012141a4ced08232e124044
parent 324067 222cd7ec93a24eb3daf20e4ff6317ee7ef0b5398
child 324069 74eb89122c1f7a6b6ae18f3a242a0fa330930afb
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahunt, ritu
bugs1244722
milestone47.0a2
Bug 1244722 - TabQueueHelper.canDrawOverlays(): Implement workaround for Android bug. r=ahunt a=ritu Android's Settings.canDrawOverlays() returns true/false for one of the packages with the same sharedUserId. There's no guarantee that this is actually the current package. Instead of relying on Settings.canDrawOverlays() we just try to add and remove an invisible view through WindowManger. If this succeeds then we obviously can draw overlays and if this fails then we seem to not have the permission. MozReview-Commit-ID: 1jdrQ7iV3ek
mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueHelper.java
--- a/mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/tabqueue/TabQueueHelper.java
@@ -2,37 +2,39 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tabqueue;
 
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.annotation.TargetApi;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.os.Build;
-import android.provider.Settings;
+import android.graphics.PixelFormat;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.content.ContextCompat;
 import android.text.TextUtils;
 import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import java.util.ArrayList;
 import java.util.List;
 
 public class TabQueueHelper {
@@ -63,17 +65,39 @@ public class TabQueueHelper {
      *
      * @return true if the specified context can draw on top of other apps, false otherwise.
      */
     public static boolean canDrawOverlays(Context context) {
         if (AppConstants.Versions.preM) {
             return true; // We got the permission at install time.
         }
 
-        return Settings.canDrawOverlays(context);
+        // It would be nice to just use Settings.canDrawOverlays() - but this helper is buggy for
+        // apps using sharedUserId (See bug 1244722).
+        // Instead we'll add and remove an invisible view. If this is successful then we seem to
+        // have permission to draw overlays.
+
+        View view = new View(context);
+        view.setVisibility(View.INVISIBLE);
+
+        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
+                1, 1,
+                WindowManager.LayoutParams.TYPE_PHONE,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
+                PixelFormat.TRANSLUCENT);
+
+        WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+
+        try {
+            windowManager.addView(view, layoutParams);
+            windowManager.removeView(view);
+            return true;
+        } catch (final SecurityException | WindowManager.BadTokenException e) {
+            return false;
+        }
     }
 
     /**
      * Check if we should show the tab queue prompt
      *
      * @param context
      * @return true if we should display the prompt, false if not.
      */