Merge "Add tracing for onTaskStackChanged" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 93caec3..c7fd3dc 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -23644,7 +23644,7 @@
 
   public static final class VolumeShaper.Configuration implements android.os.Parcelable {
     method public int describeContents();
-    method public double getDurationMillis();
+    method public long getDuration();
     method public int getInterpolatorType();
     method public static int getMaximumCurvePoints();
     method public float[] getTimes();
@@ -23670,7 +23670,7 @@
     method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
     method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
     method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
-    method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double);
+    method public android.media.VolumeShaper.Configuration.Builder setDuration(long);
     method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index bbced6c..78f911a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -25492,7 +25492,7 @@
 
   public static final class VolumeShaper.Configuration implements android.os.Parcelable {
     method public int describeContents();
-    method public double getDurationMillis();
+    method public long getDuration();
     method public int getInterpolatorType();
     method public static int getMaximumCurvePoints();
     method public float[] getTimes();
@@ -25518,7 +25518,7 @@
     method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
     method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
     method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
-    method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double);
+    method public android.media.VolumeShaper.Configuration.Builder setDuration(long);
     method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index b5cfa24..4ad78c5 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -23752,7 +23752,7 @@
 
   public static final class VolumeShaper.Configuration implements android.os.Parcelable {
     method public int describeContents();
-    method public double getDurationMillis();
+    method public long getDuration();
     method public int getInterpolatorType();
     method public static int getMaximumCurvePoints();
     method public float[] getTimes();
@@ -23778,7 +23778,7 @@
     method public android.media.VolumeShaper.Configuration.Builder scaleToEndVolume(float);
     method public android.media.VolumeShaper.Configuration.Builder scaleToStartVolume(float);
     method public android.media.VolumeShaper.Configuration.Builder setCurve(float[], float[]);
-    method public android.media.VolumeShaper.Configuration.Builder setDurationMillis(double);
+    method public android.media.VolumeShaper.Configuration.Builder setDuration(long);
     method public android.media.VolumeShaper.Configuration.Builder setInterpolatorType(int);
   }
 
diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java
index 2123deb..b519ec9 100644
--- a/core/java/android/webkit/WebViewZygote.java
+++ b/core/java/android/webkit/WebViewZygote.java
@@ -40,6 +40,7 @@
 
     private static final String WEBVIEW_ZYGOTE_SERVICE_32 = "webview_zygote32";
     private static final String WEBVIEW_ZYGOTE_SERVICE_64 = "webview_zygote64";
+    private static final String WEBVIEW_ZYGOTE_SOCKET = "webview_zygote";
 
     /**
      * Lock object that protects all other static members.
@@ -202,7 +203,7 @@
         }
 
         try {
-            sZygote = new ZygoteProcess("webview_zygote", null);
+            sZygote = new ZygoteProcess(WEBVIEW_ZYGOTE_SOCKET, null);
 
             // All the work below is usually done by LoadedApk, but the zygote can't talk to
             // PackageManager or construct a LoadedApk since it's single-threaded pre-fork, so
@@ -217,6 +218,8 @@
             final String zip = (zipPaths.size() == 1) ? zipPaths.get(0) :
                     TextUtils.join(File.pathSeparator, zipPaths);
 
+            waitForZygote();
+
             Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath);
             sZygote.preloadPackageForAbi(zip, librarySearchPath, sPackageCacheKey,
                                          Build.SUPPORTED_ABIS[0]);
@@ -225,4 +228,25 @@
             sZygote = null;
         }
     }
+
+    /**
+     * Wait until a connection to the Zygote can be established.
+     */
+    private static void waitForZygote() {
+        while (true) {
+            try {
+                final ZygoteProcess.ZygoteState zs =
+                        ZygoteProcess.ZygoteState.connect(WEBVIEW_ZYGOTE_SOCKET);
+                zs.close();
+                break;
+            } catch (IOException ioe) {
+                Log.w(LOGTAG, "Got error connecting to zygote, retrying. msg= " + ioe.getMessage());
+            }
+
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException ie) {
+            }
+        }
+    }
 }
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 00d786a..244d6e5 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -93,6 +93,16 @@
      */
     public static final int FLAG_ENCRYPTED = 1;
 
+    /**
+     * A private flag that's only available to system server to indicate that this key is part of
+     * device encryption flow so it receives special treatment from keystore. For example this key
+     * will not be super encrypted, and it will be stored separately under an unique UID instead
+     * of the caller UID i.e. SYSTEM.
+     *
+     * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
+     */
+    public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
+
     // States
     public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
 
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 64b10ab..bab4010 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -351,6 +351,9 @@
             }
         } else if (param instanceof KeyProtection) {
             spec = (KeyProtection) param;
+            if (spec.isCriticalToDeviceEncryption()) {
+                flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
+            }
         } else {
             throw new KeyStoreException(
                     "Unsupported protection parameter class:" + param.getClass().getName()
@@ -719,6 +722,10 @@
         } catch (IllegalArgumentException | IllegalStateException e) {
             throw new KeyStoreException(e);
         }
+        int flags = 0;
+        if (params.isCriticalToDeviceEncryption()) {
+            flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
+        }
 
         Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
         String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias;
@@ -728,7 +735,7 @@
                 KeymasterDefs.KM_KEY_FORMAT_RAW,
                 keyMaterial,
                 mUid,
-                0, // flags
+                flags,
                 new KeyCharacteristics());
         if (errorCode != KeyStore.NO_ERROR) {
             throw new KeyStoreException("Failed to import secret key. Keystore error code: "
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 2592a97..2eb0663 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -227,6 +227,7 @@
     private final boolean mUserAuthenticationValidWhileOnBody;
     private final boolean mInvalidatedByBiometricEnrollment;
     private final long mBoundToSecureUserId;
+    private final boolean mCriticalToDeviceEncryption;
 
     private KeyProtection(
             Date keyValidityStart,
@@ -242,7 +243,8 @@
             int userAuthenticationValidityDurationSeconds,
             boolean userAuthenticationValidWhileOnBody,
             boolean invalidatedByBiometricEnrollment,
-            long boundToSecureUserId) {
+            long boundToSecureUserId,
+            boolean criticalToDeviceEncryption) {
         mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
         mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
         mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -259,6 +261,7 @@
         mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
         mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
         mBoundToSecureUserId = boundToSecureUserId;
+        mCriticalToDeviceEncryption = criticalToDeviceEncryption;
     }
 
     /**
@@ -458,6 +461,16 @@
     }
 
     /**
+     * Return whether this key is critical to the device encryption flow.
+     *
+     * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION
+     * @hide
+     */
+    public boolean isCriticalToDeviceEncryption() {
+        return mCriticalToDeviceEncryption;
+    }
+
+    /**
      * Builder of {@link KeyProtection} instances.
      */
     public final static class Builder {
@@ -477,6 +490,7 @@
         private boolean mInvalidatedByBiometricEnrollment = true;
 
         private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
+        private boolean mCriticalToDeviceEncryption = false;
         /**
          * Creates a new instance of the {@code Builder}.
          *
@@ -817,6 +831,20 @@
         }
 
         /**
+         * Set whether this key is critical to the device encryption flow
+         *
+         * This is a special flag only available to system servers to indicate the current key
+         * is part of the device encryption flow.
+         *
+         * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION
+         * @hide
+         */
+        public Builder setCriticalToDeviceEncryption(boolean critical) {
+            mCriticalToDeviceEncryption = critical;
+            return this;
+        }
+
+        /**
          * Builds an instance of {@link KeyProtection}.
          *
          * @throws IllegalArgumentException if a required field is missing
@@ -837,7 +865,8 @@
                     mUserAuthenticationValidityDurationSeconds,
                     mUserAuthenticationValidWhileOnBody,
                     mInvalidatedByBiometricEnrollment,
-                    mBoundToSecureUserId);
+                    mBoundToSecureUserId,
+                    mCriticalToDeviceEncryption);
         }
     }
 }
diff --git a/media/java/android/media/VolumeShaper.java b/media/java/android/media/VolumeShaper.java
index 1dda6a4..8f4721f 100644
--- a/media/java/android/media/VolumeShaper.java
+++ b/media/java/android/media/VolumeShaper.java
@@ -301,7 +301,7 @@
                 .setInterpolatorType(INTERPOLATOR_TYPE_LINEAR)
                 .setCurve(new float[] {0.f, 1.f} /* times */,
                         new float[] {0.f, 1.f} /* volumes */)
-                .setDurationMillis(1000.)
+                .setDuration(1000)
                 .build();
 
         /**
@@ -314,7 +314,7 @@
                 .setInterpolatorType(INTERPOLATOR_TYPE_CUBIC)
                 .setCurve(new float[] {0.f, 1.f} /* times */,
                         new float[] {0.f, 1.f}  /* volumes */)
-                .setDurationMillis(1000.)
+                .setDuration(1000)
                 .build();
 
         /**
@@ -348,12 +348,12 @@
             SINE_RAMP = new VolumeShaper.Configuration.Builder()
                 .setInterpolatorType(INTERPOLATOR_TYPE_CUBIC)
                 .setCurve(times, sines)
-                .setDurationMillis(1000.)
+                .setDuration(1000)
                 .build();
             SCURVE_RAMP = new VolumeShaper.Configuration.Builder()
                 .setInterpolatorType(INTERPOLATOR_TYPE_CUBIC)
                 .setCurve(times, scurve)
-                .setDurationMillis(1000.)
+                .setDuration(1000)
                 .build();
         }
 
@@ -569,8 +569,9 @@
         /**
          * Returns the duration of the volume shape in milliseconds.
          */
-        public double getDurationMillis() {
-            return mDurationMs;
+        public long getDuration() {
+            // casting is safe here as the duration was set as a long in the Builder
+            return (long) mDurationMs;
         }
 
         /**
@@ -700,7 +701,7 @@
          *             .setInterpolatorType(VolumeShaper.Configuration.INTERPOLATOR_TYPE_LINEAR)
          *             .setCurve(new float[] { 0.f, 1.f }, // times
          *                       new float[] { 0.f, 1.f }) // volumes
-         *             .setDurationMillis(1000.)
+         *             .setDuration(1000)
          *             .build();
          * </pre>
          * <p>
@@ -731,7 +732,7 @@
                 mId = configuration.getId();
                 mOptionFlags = configuration.getAllOptionFlags();
                 mInterpolatorType = configuration.getInterpolatorType();
-                mDurationMs = configuration.getDurationMillis();
+                mDurationMs = configuration.getDuration();
                 mTimes = configuration.getTimes().clone();
                 mVolumes = configuration.getVolumes().clone();
             }
@@ -810,12 +811,12 @@
              * @throws IllegalArgumentException if {@code durationMillis}
              *         is not strictly positive.
              */
-            public @NonNull Builder setDurationMillis(double durationMillis) {
-                if (durationMillis <= 0.) {
+            public @NonNull Builder setDuration(long durationMillis) {
+                if (durationMillis <= 0) {
                     throw new IllegalArgumentException(
                             "duration: " + durationMillis + " not positive");
                 }
-                mDurationMs = durationMillis;
+                mDurationMs = (double) durationMillis;
                 return this;
             }
 
@@ -833,7 +834,7 @@
              * time (x) coordinates should be monotonically increasing, from 0.f to 1.f;
              * volume (y) coordinates must be within 0.f to 1.f.
              * <p>
-             * The time scale is set by {@link #setDurationMillis}.
+             * The time scale is set by {@link #setDuration}.
              * <p>
              * @param times an array of float values representing
              *        the time line of the volume curve.
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index e15df14..044392c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -130,6 +130,12 @@
     <!-- Bluetooth settings. The user-visible string that is used whenever referring to the SAP profile (sharing SIM card). -->
     <string name="bluetooth_profile_sap">SIM Access</string>
 
+    <!-- Bluetooth settings. The user-visible string for the setting controlling whether to use a high-quality codec if the device supports it, along with the name of the codec (eg AAC, LDAC, aptX) -->
+    <string name="bluetooth_profile_a2dp_high_quality">Use high quality audio: <xliff:g id="codec_name">%1$s</xliff:g></string>
+
+    <!-- Bluetooth settings. Similar to bluetooth_profile_a2dp_high_quality, but used when the device supports high quality audio but we don't know which codec that will be used. -->
+    <string name="bluetooth_profile_a2dp_high_quality_unknown_codec">Use high quality audio</string>
+
     <!-- Bluetooth settings.  Connection options screen.  The summary for the A2DP checkbox preference when A2DP is connected. -->
     <string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string>
     <!-- Bluetooth settings.  Connection options screen.  The summary for the headset checkbox preference when headset is connected. -->
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 55f32d7..bf39bc4 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -22,9 +22,6 @@
         android:sharedUserId="android.uid.systemui"
         coreApp="true">
 
-    <protected-broadcast android:name="com.android.systemui.action.PLUGIN_CHANGED" />
-
-
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
index a8daed5..f663315 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginInstanceManager.java
@@ -155,10 +155,6 @@
                 new ComponentName(info.mPackage, info.mClass),
                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                 PackageManager.DONT_KILL_APP);
-        final String pkg = info.mPackage;
-        final Intent intent = new Intent(PluginManager.PLUGIN_CHANGED,
-                pkg != null ? Uri.fromParts("package", pkg, null) : null);
-        mContext.sendBroadcast(intent);
     }
 
     public <T> boolean dependsOn(Plugin p, Class<T> cls) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 4dec6c7..2cf06c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -262,17 +262,15 @@
 
     private boolean hasImportanceChanged() {
         return mSingleNotificationChannel != null &&
+                mChannelEnabledSwitch != null &&
                 mStartingUserImportance != getSelectedImportance();
     }
 
     private void saveImportance() {
-        if (mSingleNotificationChannel == null) {
+        if (!hasImportanceChanged()) {
             return;
         }
-        int selectedImportance = getSelectedImportance();
-        if (selectedImportance == mStartingUserImportance) {
-            return;
-        }
+        final int selectedImportance = getSelectedImportance();
         MetricsLogger.action(mContext, MetricsEvent.ACTION_SAVE_IMPORTANCE,
                 selectedImportance - mStartingUserImportance);
         mSingleNotificationChannel.setImportance(selectedImportance);
@@ -386,7 +384,7 @@
 
     @Override
     public boolean willBeRemoved() {
-        return !mChannelEnabledSwitch.isChecked();
+        return mChannelEnabledSwitch != null && !mChannelEnabledSwitch.isChecked();
     }
 
     @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 907928f..2b14b31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -778,4 +778,9 @@
         enabledSwitch.setChecked(true);
         assertEquals(View.VISIBLE, settingsLink.getVisibility());
     }
+
+    @Test
+    public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
+        assertFalse(mNotificationInfo.willBeRemoved());
+    }
 }
diff --git a/services/core/java/com/android/server/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/SyntheticPasswordCrypto.java
index 12d91c5..71ab2a5 100644
--- a/services/core/java/com/android/server/SyntheticPasswordCrypto.java
+++ b/services/core/java/com/android/server/SyntheticPasswordCrypto.java
@@ -139,12 +139,14 @@
             keyStore.load(null);
             KeyProtection.Builder builder = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
                     .setBlockModes(KeyProperties.BLOCK_MODE_GCM)
-                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE);
+                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+                    .setCriticalToDeviceEncryption(true);
             if (sid != 0) {
                 builder.setUserAuthenticationRequired(true)
                         .setBoundToSpecificSecureUserId(sid)
                         .setUserAuthenticationValidityDurationSeconds(USER_AUTHENTICATION_VALIDITY);
             }
+
             keyStore.setEntry(keyAlias,
                     new KeyStore.SecretKeyEntry(secretKey),
                     builder.build());
diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
index aea4cb5..b0f84fe 100644
--- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
+++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java
@@ -57,7 +57,7 @@
                 .setCurve(new float[] { 0.f, 1.f } /* times */,
                     new float[] { 1.f, 0.2f } /* volumes */)
                 .setOptionFlags(VolumeShaper.Configuration.OPTION_FLAG_CLOCK_TIME)
-                .setDurationMillis(MediaFocusControl.getFocusRampTimeMs(
+                .setDuration(MediaFocusControl.getFocusRampTimeMs(
                     AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
                     new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION)
                             .build()))
diff --git a/tools/aapt2/cmd/Compile.cpp b/tools/aapt2/cmd/Compile.cpp
index 423e790..b93c6ec 100644
--- a/tools/aapt2/cmd/Compile.cpp
+++ b/tools/aapt2/cmd/Compile.cpp
@@ -365,6 +365,21 @@
   return true;
 }
 
+static bool IsValidFile(IAaptContext* context, const StringPiece& input_path) {
+  const file::FileType file_type = file::GetFileType(input_path);
+  if (file_type != file::FileType::kRegular && file_type != file::FileType::kSymlink) {
+    if (file_type == file::FileType::kDirectory) {
+      context->GetDiagnostics()->Error(DiagMessage(input_path)
+                                       << "resource file cannot be a directory");
+    } else {
+      context->GetDiagnostics()->Error(DiagMessage(input_path)
+                                       << "not a valid resource file");
+    }
+    return false;
+  }
+  return true;
+}
+
 static bool CompileXml(IAaptContext* context, const CompileOptions& options,
                        const ResourcePathData& path_data, IArchiveWriter* writer,
                        const std::string& output_path) {
@@ -569,7 +584,8 @@
   std::string error_str;
   Maybe<android::FileMap> f = file::MmapPath(path_data.source.path, &error_str);
   if (!f) {
-    context->GetDiagnostics()->Error(DiagMessage(path_data.source) << error_str);
+    context->GetDiagnostics()->Error(DiagMessage(path_data.source) << "failed to mmap file: "
+                                     << error_str);
     return false;
   }
 
@@ -697,6 +713,11 @@
       context.GetDiagnostics()->Note(DiagMessage(path_data.source) << "processing");
     }
 
+    if (!IsValidFile(&context, path_data.source.path)) {
+      error = true;
+      continue;
+    }
+
     if (path_data.resource_dir == "values") {
       // Overwrite the extension.
       path_data.extension = "arsc";
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 0c19c7a..27ab22b 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -333,7 +333,7 @@
   // Provider actions.
   application_action["provider"] = component_action;
   application_action["provider"]["grant-uri-permissions"];
-  application_action["provider"]["path-permissions"];
+  application_action["provider"]["path-permission"];
 
   return true;
 }