Merge "Conslidate @MainHandler and similar to @Main (and similar)."
diff --git a/api/current.txt b/api/current.txt
index 86aa80b..94a913d 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3955,6 +3955,7 @@
public class ActivityManager {
method public int addAppTask(@NonNull android.app.Activity, @NonNull android.content.Intent, @Nullable android.app.ActivityManager.TaskDescription, @NonNull android.graphics.Bitmap);
+ method public void appNotResponding(@NonNull String);
method public boolean clearApplicationUserData();
method public void clearWatchHeapLimit();
method @RequiresPermission(android.Manifest.permission.DUMP) public void dumpPackageState(java.io.FileDescriptor, String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 05e2ca5..c0f8ceb 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8981,6 +8981,34 @@
field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
}
+ public abstract class CellIdentity implements android.os.Parcelable {
+ method @NonNull public abstract android.telephony.CellLocation asCellLocation();
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityNr extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.CellLocation asCellLocation();
+ }
+
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
public final class DataFailCause {
field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
field public static final int ACCESS_BLOCK = 2087; // 0x827
@@ -9580,6 +9608,7 @@
}
public final class PreciseCallState implements android.os.Parcelable {
+ ctor public PreciseCallState(int, int, int, int, int);
method public int describeContents();
method public int getBackgroundCallState();
method public int getForegroundCallState();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 68bdfae..3f9f7fb 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4547,4 +4547,17 @@
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Method for the app to tell system that it's wedged and would like to trigger an ANR.
+ *
+ * @param reason The description of that what happened
+ */
+ public void appNotResponding(@NonNull final String reason) {
+ try {
+ getService().appNotResponding(reason);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 112bd30..e8494c4 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -583,4 +583,9 @@
* unlockProgressListener can be null if monitoring progress is not necessary.
*/
boolean startUserInForegroundWithListener(int userid, IProgressListener unlockProgressListener);
+
+ /**
+ * Method for the app to tell system that it's wedged and would like to trigger an ANR.
+ */
+ void appNotResponding(String reason);
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c5a147a..7967708 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -11050,6 +11050,7 @@
case ACTION_MEDIA_SCANNER_FINISHED:
case ACTION_MEDIA_SCANNER_SCAN_FILE:
case ACTION_PACKAGE_NEEDS_VERIFICATION:
+ case ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION:
case ACTION_PACKAGE_VERIFIED:
case ACTION_PACKAGE_ENABLE_ROLLBACK:
// Ignore legacy actions
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 51a9c86..e5f2c3a 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -24,7 +24,6 @@
import android.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
@@ -993,8 +992,11 @@
() -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
}
- public void onCellLocationChanged(Bundle bundle) {
- CellLocation location = CellLocation.newFromBundle(bundle);
+ public void onCellLocationChanged(CellIdentity cellIdentity) {
+ // There is no system/public API to create an CellIdentity in system server,
+ // so the server pass a null to indicate an empty initial location.
+ CellLocation location =
+ cellIdentity == null ? CellLocation.getEmpty() : cellIdentity.asCellLocation();
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index f574160..1b2feda 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -22,7 +22,6 @@
import android.annotation.TestApi;
import android.content.Context;
import android.os.Binder;
-import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Annotation.CallState;
@@ -633,10 +632,14 @@
}
/**
- * TODO change from bundle to CellLocation?
+ * Notify {@link android.telephony.CellLocation} changed.
+ *
+ * <p>To be compatible with {@link TelephonyRegistry}, use {@link CellIdentity} which is
+ * parcelable, and convert to CellLocation in client code.
+ *
* @hide
*/
- public void notifyCellLocation(int subId, Bundle cellLocation) {
+ public void notifyCellLocation(int subId, CellIdentity cellLocation) {
try {
sRegistry.notifyCellLocationForSubscriber(subId, cellLocation);
} catch (RemoteException ex) {
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index cb67309..6c7e3dc 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -16,8 +16,8 @@
package com.android.internal.telephony;
-import android.os.Bundle;
import android.telephony.CallAttributes;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.PhoneCapability;
@@ -37,8 +37,8 @@
void onMessageWaitingIndicatorChanged(boolean mwi);
void onCallForwardingIndicatorChanged(boolean cfi);
- // we use bundle here instead of CellLocation so it can get the right subclass
- void onCellLocationChanged(in Bundle location);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void onCellLocationChanged(in CellIdentity location);
void onCallStateChanged(int state, String incomingNumber);
void onDataConnectionStateChanged(int state, int networkType);
void onDataActivity(int direction);
@@ -63,4 +63,3 @@
void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
}
-
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index f954679..4e40503 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -19,8 +19,8 @@
import android.content.Intent;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
-import android.os.Bundle;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.PhoneCapability;
@@ -66,9 +66,9 @@
int phoneId, int subId, String apnType, in PreciseDataConnectionState preciseState);
@UnsupportedAppUsage
void notifyDataConnectionFailed(String apnType);
- @UnsupportedAppUsage(maxTargetSdk = 28)
- void notifyCellLocation(in Bundle cellLocation);
- void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void notifyCellLocation(in CellIdentity cellLocation);
+ void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
diff --git a/core/tests/overlaytests/device/res/layout/layout.xml b/core/tests/overlaytests/device/res/layout/layout.xml
new file mode 100644
index 0000000..e12c715
--- /dev/null
+++ b/core/tests/overlaytests/device/res/layout/layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:id="@id/view_1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@id/view_2"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="none"/>
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@id/view_3"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="none" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/tests/overlaytests/device/res/values/config.xml b/core/tests/overlaytests/device/res/values/config.xml
index c692a26..e918268 100644
--- a/core/tests/overlaytests/device/res/values/config.xml
+++ b/core/tests/overlaytests/device/res/values/config.xml
@@ -56,4 +56,16 @@
<item>17</item>
<item>19</item>
</integer-array>
+
+ <attr name="customAttribute" />
+ <id name="view_1" />
+ <id name="view_2" />
+ <id name="view_3" />
+
+ <!-- Stabilize the ids of attributes and ids used in test layouts so that they differ from the
+ overlay resource ids -->
+ <public type="attr" name="customAttribute" id="0x7f200000"/>
+ <public type="id" name="view_1" id="0x7f210000"/>
+ <public type="id" name="view_2" id="0x7f210001"/>
+ <public type="id" name="view_3" id="0x7f210002"/>
</resources>
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index fdb6bbb..636f4c8 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -18,20 +18,26 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.LocaleList;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.util.Xml;
+import android.view.LayoutInflater;
+import android.view.View;
import androidx.test.InstrumentationRegistry;
import com.android.internal.util.ArrayUtils;
+import com.android.overlaytest.view.TestTextView;
import org.junit.Before;
import org.junit.Ignore;
@@ -45,6 +51,7 @@
@Ignore
public abstract class OverlayBaseTest {
+ private Context mContext;
private Resources mResources;
private final int mMode;
static final int MODE_NO_OVERLAY = 0;
@@ -61,7 +68,8 @@
@Before
public void setUp() {
- mResources = InstrumentationRegistry.getContext().getResources();
+ mContext = InstrumentationRegistry.getContext();
+ mResources = mContext.getResources();
}
private int calculateRawResourceChecksum(int resId) throws Throwable {
@@ -321,6 +329,50 @@
assertEquals("com.android.overlaytest", contents);
}
+ @Test
+ public void testRewrite() throws Throwable {
+ final TypedValue result = new TypedValue();
+ mResources.getValue(R.string.str, result, true);
+ assertEquals(result.resourceId & 0xff000000, 0x7f000000);
+ }
+
+ @Test
+ public void testOverlayLayout() throws Throwable {
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ final View layout = inflater.inflate(R.layout.layout, null);
+ assertNotNull(layout.findViewById(R.id.view_1));
+
+ final TestTextView view2 = layout.findViewById(R.id.view_2);
+ assertNotNull(view2);
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ assertEquals("none", view2.getCustomAttributeValue());
+ break;
+ case MODE_SINGLE_OVERLAY:
+ assertEquals("single", view2.getCustomAttributeValue());
+ break;
+ case MODE_MULTIPLE_OVERLAYS:
+ assertEquals("multiple", view2.getCustomAttributeValue());
+ break;
+ default:
+ fail("Unknown mode " + mMode);
+ }
+
+ final TestTextView view3 = layout.findViewById(R.id.view_3);
+ assertNotNull(view3);
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ assertEquals("none", view3.getCustomAttributeValue());
+ break;
+ case MODE_SINGLE_OVERLAY:
+ case MODE_MULTIPLE_OVERLAYS:
+ assertEquals("overlaid", view3.getCustomAttributeValue());
+ break;
+ default:
+ fail("Unknown mode " + mMode);
+ }
+ }
+
/*
* testMatrix* tests
*
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java b/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java
new file mode 100644
index 0000000..2245e2b
--- /dev/null
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.overlaytest.view;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+public class TestTextView extends TextView {
+
+ private final String mCustomAttributeValue;
+
+ public TestTextView(Context context, AttributeSet attrs) {
+ this(context, attrs, com.android.internal.R.attr.textViewStyle, 0);
+ }
+
+ public TestTextView(Context context, AttributeSet attrs,
+ int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ int[] testResources = new int[]{com.android.overlaytest.R.attr.customAttribute};
+ final Resources.Theme theme = context.getTheme();
+ TypedArray typedArray = theme.obtainStyledAttributes(attrs, testResources, defStyleAttr,
+ defStyleRes);
+ mCustomAttributeValue = typedArray.getString(0);
+ }
+
+ public String getCustomAttributeValue() {
+ return mCustomAttributeValue;
+ }
+}
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
index 7d28408..873ca3c 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
@@ -19,5 +19,6 @@
android:versionCode="1"
android:versionName="1.0">
<application android:hasCode="false" />
- <overlay android:targetPackage="com.android.overlaytest" />
+ <overlay android:targetPackage="com.android.overlaytest"
+ android:resourcesMap="@xml/overlays"/>
</manifest>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml
new file mode 100644
index 0000000..7b63605
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:id="@+id/view_1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@+id/view_2"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="@string/str" />
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@+id/view_3"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="overlaid" />
+ </LinearLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
index 972137a..74c4963 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="str">single</string>
- <string name="str2">single</string>
<integer name="matrix_101000">300</integer>
<integer name="matrix_101001">300</integer>
<integer name="matrix_101010">300</integer>
@@ -18,7 +17,6 @@
<integer name="matrix_111101">300</integer>
<integer name="matrix_111110">300</integer>
<integer name="matrix_111111">300</integer>
- <bool name="usually_false">true</bool>
<integer-array name="fibonacci">
<item>21</item>
<item>13</item>
@@ -29,7 +27,10 @@
<item>1</item>
<item>1</item>
</integer-array>
+
<!-- The following integer does not exist in the original package. Idmap
generation should therefore ignore it. -->
<integer name="integer_not_in_original_package">0</integer>
+
+ <attr name="customAttribute" />
</resources>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml
new file mode 100644
index 0000000..38e5fa1
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<overlay>
+ <item target="drawable/drawable" value="@drawable/drawable"/>
+ <item target="layout/layout" value="@layout/layout"/>
+ <item target="raw/lorem_ipsum" value="@raw/lorem_ipsum"/>
+ <item target="xml/integer" value="@xml/integer"/>
+ <item target="string/str" value="@string/str"/>
+ <item target="string/str2" value="single"/>
+
+ <item target="integer/matrix_100100" value="@integer/matrix_100100"/>
+ <item target="integer/matrix_100101" value="@integer/matrix_100101"/>
+ <item target="integer/matrix_100110" value="@integer/matrix_100110"/>
+ <item target="integer/matrix_100110" value="@integer/matrix_100110"/>
+ <item target="integer/matrix_100111" value="@integer/matrix_100111"/>
+ <item target="integer/matrix_101000" value="@integer/matrix_101000"/>
+ <item target="integer/matrix_101001" value="@integer/matrix_101001"/>
+ <item target="integer/matrix_101010" value="@integer/matrix_101010"/>
+ <item target="integer/matrix_101011" value="@integer/matrix_101011"/>
+ <item target="integer/matrix_101100" value="@integer/matrix_101100"/>
+ <item target="integer/matrix_101101" value="@integer/matrix_101101"/>
+ <item target="integer/matrix_101110" value="@integer/matrix_101110"/>
+ <item target="integer/matrix_101111" value="@integer/matrix_101111"/>
+ <item target="integer/matrix_110100" value="@integer/matrix_110100"/>
+ <item target="integer/matrix_110101" value="@integer/matrix_110101"/>
+ <item target="integer/matrix_110110" value="@integer/matrix_110110"/>
+ <item target="integer/matrix_110111" value="@integer/matrix_110111"/>
+ <item target="integer/matrix_111000" value="@integer/matrix_111000"/>
+ <item target="integer/matrix_111001" value="@integer/matrix_111001"/>
+ <item target="integer/matrix_111010" value="@integer/matrix_111010"/>
+ <item target="integer/matrix_111011" value="@integer/matrix_111011"/>
+ <item target="integer/matrix_111100" value="@integer/matrix_111100"/>
+ <item target="integer/matrix_111101" value="@integer/matrix_111101"/>
+ <item target="integer/matrix_111110" value="@integer/matrix_111110"/>
+ <item target="integer/matrix_111111" value="@integer/matrix_111111"/>
+
+ <item target="bool/usually_false" value="true"/>
+
+ <item target="array/fibonacci" value="@array/fibonacci"/>
+
+ <item target="attr/customAttribute" value="@attr/customAttribute"/>
+ <item target="id/view_1" value="@id/view_1"/>
+ <item target="id/view_2" value="@id/view_2"/>
+ <item target="id/view_3" value="@id/view_3"/>
+</overlay>
+
+
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index ce3bfff..0b2fd9e 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -57,7 +57,7 @@
const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
const size_t offset = dtohl(data_header_->string_pool_index_offset);
- if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+ if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
return idmap_string_pool_->stringAt(idx - offset, outLen);
}
@@ -66,13 +66,17 @@
const char* OverlayStringPool::string8At(size_t idx, size_t* outLen) const {
const size_t offset = dtohl(data_header_->string_pool_index_offset);
- if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+ if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
return idmap_string_pool_->string8At(idx - offset, outLen);
}
return ResStringPool::string8At(idx, outLen);
}
+size_t OverlayStringPool::size() const {
+ return ResStringPool::size() + (idmap_string_pool_ != nullptr ? idmap_string_pool_->size() : 0U);
+}
+
OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
const Idmap_overlay_entry* entries,
uint8_t target_assigned_package_id)
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index ab4c9c2..ccb57f3 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -40,8 +40,9 @@
class OverlayStringPool : public ResStringPool {
public:
virtual ~OverlayStringPool();
- virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
- virtual const char* string8At(size_t idx, size_t* outLen) const;
+ const char16_t* stringAt(size_t idx, size_t* outLen) const override;
+ const char* string8At(size_t idx, size_t* outLen) const override;
+ size_t size() const override;
explicit OverlayStringPool(const LoadedIdmap* loaded_idmap);
private:
@@ -53,8 +54,8 @@
// resources to the resource id of corresponding target resources.
class OverlayDynamicRefTable : public DynamicRefTable {
public:
- virtual ~OverlayDynamicRefTable() = default;
- virtual status_t lookupResourceId(uint32_t* resId) const;
+ ~OverlayDynamicRefTable() override = default;
+ status_t lookupResourceId(uint32_t* resId) const override;
private:
explicit OverlayDynamicRefTable(const Idmap_data_header* data_header,
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index b603326..35cebd4 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -520,7 +520,7 @@
ssize_t indexOfString(const char16_t* str, size_t strLen) const;
- size_t size() const;
+ virtual size_t size() const;
size_t styleCount() const;
size_t bytes() const;
const void* data() const;
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index f363a73..40a7dfc 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -67,6 +67,27 @@
public static final int PACKAGE_COMPANION = 14;
@IntDef(value = {
+ INTEGRITY_VERIFICATION_ALLOW,
+ INTEGRITY_VERIFICATION_REJECT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IntegrityVerificationResult {}
+
+ /**
+ * Used as the {@code verificationCode} argument for
+ * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
+ * integrity component allows the install to proceed.
+ */
+ public static final int INTEGRITY_VERIFICATION_ALLOW = 1;
+
+ /**
+ * Used as the {@code verificationCode} argument for
+ * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
+ * integrity component does not allow install to proceed.
+ */
+ public static final int INTEGRITY_VERIFICATION_REJECT = 0;
+
+ @IntDef(value = {
PACKAGE_SYSTEM,
PACKAGE_SETUP_WIZARD,
PACKAGE_INSTALLER,
@@ -842,13 +863,13 @@
* {@link Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION package verification
* broadcast} to respond to the package manager. The response must include
* the {@code verificationCode} which is one of
- * {@link PackageManager#VERIFICATION_ALLOW} or
- * {@link PackageManager#VERIFICATION_REJECT}.
+ * {@link #INTEGRITY_VERIFICATION_ALLOW} and {@link #INTEGRITY_VERIFICATION_REJECT}.
*
* @param verificationId pending package identifier as passed via the
* {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
- * @param verificationResult either {@link PackageManager#VERIFICATION_ALLOW}
- * or {@link PackageManager#VERIFICATION_REJECT}.
+ * @param verificationResult either {@link #INTEGRITY_VERIFICATION_ALLOW}
+ * or {@link #INTEGRITY_VERIFICATION_REJECT}.
*/
- public abstract void setIntegrityVerificationResult(int verificationId, int verificationResult);
+ public abstract void setIntegrityVerificationResult(int verificationId,
+ @IntegrityVerificationResult int verificationResult);
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 13eb556..46ff718 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -46,6 +46,7 @@
import android.telephony.Annotation.SrvccState;
import android.telephony.CallAttributes;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
import android.telephony.DataFailCause;
@@ -207,7 +208,7 @@
// Connection state of default APN type data (i.e. internet) of phones
private int[] mDataConnectionState;
- private Bundle[] mCellLocation;
+ private CellIdentity[] mCellIdentity;
private int[] mDataConnectionNetworkType;
@@ -295,7 +296,7 @@
int numPhones = getTelephonyManager().getPhoneCount();
for (int sub = 0; sub < numPhones; sub++) {
TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
- mCellLocation[sub]);
+ mCellIdentity[sub]);
}
break;
}
@@ -404,7 +405,7 @@
mSignalStrength = copyOf(mSignalStrength, mNumPhones);
mMessageWaiting = copyOf(mMessageWaiting, mNumPhones);
mCallForwarding = copyOf(mCallForwarding, mNumPhones);
- mCellLocation = copyOf(mCellLocation, mNumPhones);
+ mCellIdentity = copyOf(mCellIdentity, mNumPhones);
mSrvccState = copyOf(mSrvccState, mNumPhones);
mPreciseCallState = copyOf(mPreciseCallState, mNumPhones);
mForegroundCallState = copyOf(mForegroundCallState, mNumPhones);
@@ -439,31 +440,22 @@
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mPreciseCallState[i] = new PreciseCallState();
+ mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
-
- // Note that location can be null for non-phone builds like
- // like the generic one.
- CellLocation location = CellLocation.getEmpty();
- if (location != null) {
- for (int i = oldNumPhones; i < mNumPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
}
private void cutListToSize(List list, int size) {
@@ -503,7 +495,7 @@
mSignalStrength = new SignalStrength[numPhones];
mMessageWaiting = new boolean[numPhones];
mCallForwarding = new boolean[numPhones];
- mCellLocation = new Bundle[numPhones];
+ mCellIdentity = new CellIdentity[numPhones];
mSrvccState = new int[numPhones];
mPreciseCallState = new PreciseCallState[numPhones];
mForegroundCallState = new int[numPhones];
@@ -532,31 +524,23 @@
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mPreciseCallState[i] = new PreciseCallState();
+ mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
- // Note that location can be null for non-phone builds like
- // like the generic one.
- if (location != null) {
- for (int i = 0; i < numPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
-
mAppOps = mContext.getSystemService(AppOpsManager.class);
}
@@ -837,11 +821,10 @@
}
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("listen: mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(
- new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -1629,11 +1612,13 @@
broadcastDataConnectionFailed(apnType, subId);
}
- public void notifyCellLocation(Bundle cellLocation) {
- notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
+ @Override
+ public void notifyCellLocation(CellIdentity cellLocation) {
+ notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
}
- public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
+ @Override
+ public void notifyCellLocationForSubscriber(int subId, CellIdentity cellLocation) {
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
if (!checkNotifyPermission("notifyCellLocation()")) {
@@ -1646,7 +1631,7 @@
int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- mCellLocation[phoneId] = cellLocation;
+ mCellIdentity[phoneId] = cellLocation;
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
idMatch(r.subId, subId, phoneId) &&
@@ -1656,7 +1641,7 @@
log("notifyCellLocation: cellLocation=" + cellLocation
+ " r=" + r);
}
- r.callback.onCellLocationChanged(new Bundle(cellLocation));
+ r.callback.onCellLocationChanged(cellLocation);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2093,7 +2078,7 @@
pw.println("mCallForwarding=" + mCallForwarding[i]);
pw.println("mDataActivity=" + mDataActivity[i]);
pw.println("mDataConnectionState=" + mDataConnectionState[i]);
- pw.println("mCellLocation=" + mCellLocation[i]);
+ pw.println("mCellIdentity=" + mCellIdentity[i]);
pw.println("mCellInfo=" + mCellInfo.get(i));
pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i));
pw.println("mSrvccState=" + mSrvccState[i]);
@@ -2583,10 +2568,13 @@
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) {
+ log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
+ + mCellIdentity[phoneId]);
+ }
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
@@ -2678,6 +2666,15 @@
}
}
+ /** Returns a new PreciseCallState object with default values. */
+ private static PreciseCallState createPreciseCallState() {
+ return new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ DisconnectCause.NOT_VALID,
+ PreciseDisconnectCause.NOT_VALID);
+ }
+
/** Returns a new CallQuality object with default values. */
private static CallQuality createCallQuality() {
return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6dc49b7..d7a46fe 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7558,6 +7558,26 @@
});
}
+ @Override
+ public void appNotResponding(final String reason) {
+ final int callingPid = Binder.getCallingPid();
+
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord app = mPidsSelfLocked.get(callingPid);
+ if (app == null) {
+ throw new SecurityException("Unknown process: " + callingPid);
+ }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ app.appNotResponding(
+ null, app.info, null, null, false, "App requested: " + reason);
+ }
+ });
+ }
+ }
+
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 0b74840..9f23cdaf 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2335,7 +2335,7 @@
} else {
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
final int mode = switchOp.evalMode();
- if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+ if (mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 39c1b85..5c4479a 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -23,7 +23,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.os.Handler;
import android.os.HandlerThread;
@@ -36,6 +35,8 @@
class AppIntegrityManagerServiceImpl {
private static final String TAG = "AppIntegrityManagerServiceImpl";
+ private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+
private final Context mContext;
private final Handler mHandler;
private final PackageManagerInternal mPackageManagerInternal;
@@ -51,6 +52,11 @@
IntentFilter integrityVerificationFilter = new IntentFilter();
integrityVerificationFilter.addAction(ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+ try {
+ integrityVerificationFilter.addDataType(PACKAGE_MIME_TYPE);
+ } catch (IntentFilter.MalformedMimeTypeException e) {
+ throw new RuntimeException("Mime type malformed: should never happen.", e);
+ }
mContext.registerReceiver(
new BroadcastReceiver() {
@@ -74,7 +80,8 @@
int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
// TODO: implement this method.
Slog.i(TAG, "Received integrity verification intent " + intent.toString());
+ Slog.i(TAG, "Extras " + intent.getExtras());
mPackageManagerInternal.setIntegrityVerificationResult(
- verificationId, PackageManager.VERIFICATION_ALLOW);
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
}
}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index cfe50c6..ebf6a2e 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -16,6 +16,10 @@
package com.android.server.integrity.serializer;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
+
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Formula;
@@ -29,6 +33,7 @@
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
@@ -75,13 +80,32 @@
}
}
- private void serializeRules(List<Rule> rules, XmlSerializer xmlSerializer) throws IOException {
- xmlSerializer.startTag(NAMESPACE, RULE_LIST_TAG);
+ private void serializeRules(List<Rule> rules, XmlSerializer xmlSerializer)
+ throws RuleSerializeException {
+ try {
+ // Determine the indexing groups and the order of the rules within each indexed group.
+ Map<Integer, List<Rule>> indexedRules =
+ RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
+
+ // Write the XML formatted rules in order.
+ xmlSerializer.startTag(NAMESPACE, RULE_LIST_TAG);
+
+ serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), xmlSerializer);
+ serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), xmlSerializer);
+ serializeRuleList(indexedRules.get(NOT_INDEXED), xmlSerializer);
+
+ xmlSerializer.endTag(NAMESPACE, RULE_LIST_TAG);
+ xmlSerializer.endDocument();
+ } catch (Exception e) {
+ throw new RuleSerializeException(e.getMessage(), e);
+ }
+ }
+
+ private void serializeRuleList(List<Rule> rules, XmlSerializer xmlSerializer)
+ throws IOException {
for (Rule rule : rules) {
serializeRule(rule, xmlSerializer);
}
- xmlSerializer.endTag(NAMESPACE, RULE_LIST_TAG);
- xmlSerializer.endDocument();
}
private void serializeRule(Rule rule, XmlSerializer xmlSerializer) throws IOException {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1a64166..785ca7d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -27,6 +27,8 @@
import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_DEFAULT;
import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_VERSION_CODE;
import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
@@ -34,6 +36,7 @@
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
@@ -558,6 +561,11 @@
private static final boolean DEFAULT_VERIFY_ENABLE = true;
/**
+ * Whether integrity verification is enabled by default.
+ */
+ private static final boolean DEFAULT_INTEGRITY_VERIFY_ENABLE = true;
+
+ /**
* The default maximum time to wait for the verification agent to return in
* milliseconds.
*/
@@ -1444,6 +1452,7 @@
static final int DEFERRED_NO_KILL_POST_DELETE = 23;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24;
static final int INTEGRITY_VERIFICATION_COMPLETE = 25;
+ static final int CHECK_PENDING_INTEGRITY_VERIFICATION = 26;
static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500;
@@ -1707,13 +1716,13 @@
final int verificationId = msg.arg1;
final PackageVerificationState state = mPendingVerification.get(verificationId);
- if ((state != null) && !state.timeoutExtended()) {
+ if ((state != null) && !state.isVerificationComplete()
+ && !state.timeoutExtended()) {
final InstallParams params = state.getInstallParams();
final InstallArgs args = params.mArgs;
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
Slog.i(TAG, "Verification timed out for " + originUri);
- mPendingVerification.remove(verificationId);
final UserHandle user = args.getUser();
if (getDefaultVerificationResponse(user)
@@ -1728,11 +1737,54 @@
PackageManager.VERIFICATION_REJECT, user);
params.setReturnCode(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ state.setVerifierResponse(Binder.getCallingUid(),
+ PackageManager.VERIFICATION_REJECT);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
}
Trace.asyncTraceEnd(
TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
params.handleVerificationFinished();
+
+ }
+ break;
+ }
+ case CHECK_PENDING_INTEGRITY_VERIFICATION: {
+ final int verificationId = msg.arg1;
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
+
+ if (state != null && !state.isIntegrityVerificationComplete()) {
+ final InstallParams params = state.getInstallParams();
+ final InstallArgs args = params.mArgs;
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
+
+ Slog.i(TAG, "Integrity verification timed out for " + originUri);
+
+ state.setIntegrityVerificationResult(
+ getDefaultIntegrityVerificationResponse());
+
+ if (getDefaultIntegrityVerificationResponse()
+ == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
+ Slog.i(TAG, "Integrity check times out, continuing with " + originUri);
+ } else {
+ params.setReturnCode(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
+ Trace.asyncTraceEnd(
+ TRACE_TAG_PACKAGE_MANAGER,
+ "integrity_verification",
+ verificationId);
+
+ params.handleIntegrityVerificationFinished();
}
break;
}
@@ -1741,7 +1793,9 @@
final PackageVerificationState state = mPendingVerification.get(verificationId);
if (state == null) {
- Slog.w(TAG, "Invalid verification token " + verificationId + " received");
+ Slog.w(TAG, "Verification with id " + verificationId
+ + " not found."
+ + " It may be invalid or overridden by integrity verification");
break;
}
@@ -1750,8 +1804,6 @@
state.setVerifierResponse(response.callerUid, response.code);
if (state.isVerificationComplete()) {
- mPendingVerification.remove(verificationId);
-
final InstallParams params = state.getInstallParams();
final InstallArgs args = params.mArgs;
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
@@ -1764,6 +1816,10 @@
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
}
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
Trace.asyncTraceEnd(
TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
@@ -1773,7 +1829,40 @@
break;
}
case INTEGRITY_VERIFICATION_COMPLETE: {
- // TODO: implement this case.
+ final int verificationId = msg.arg1;
+
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
+ if (state == null) {
+ Slog.w(TAG, "Integrity verification with id " + verificationId
+ + " not found. It may be invalid or overridden by verifier");
+ break;
+ }
+
+ final int response = (Integer) msg.obj;
+
+ final InstallParams params = state.getInstallParams();
+ final InstallArgs args = params.mArgs;
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
+
+ state.setIntegrityVerificationResult(response);
+
+ if (response == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
+ Slog.i(TAG, "Integrity check passed for " + originUri);
+ } else {
+ params.setReturnCode(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
+ Trace.asyncTraceEnd(
+ TRACE_TAG_PACKAGE_MANAGER,
+ "integrity_verification",
+ verificationId);
+
+ params.handleIntegrityVerificationFinished();
break;
}
case START_INTENT_FILTER_VERIFICATIONS: {
@@ -13099,6 +13188,15 @@
}
/**
+ * Get the default integrity verification response code.
+ */
+ private int getDefaultIntegrityVerificationResponse() {
+ // We are not exposing this as a user-configurable setting because we don't want to provide
+ // an easy way to get around the integrity check.
+ return PackageManager.VERIFICATION_REJECT;
+ }
+
+ /**
* Check whether or not package verification has been enabled.
*
* @return true if verification should be performed
@@ -13141,6 +13239,15 @@
}
}
+ /**
+ * Check whether or not integrity verification has been enabled.
+ */
+ private boolean isIntegrityVerificationEnabled() {
+ // We are not exposing this as a user-configurable setting because we don't want to provide
+ // an easy way to get around the integrity check.
+ return DEFAULT_INTEGRITY_VERIFY_ENABLE;
+ }
+
@Override
public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)
throws RemoteException {
@@ -13851,6 +13958,7 @@
@NonNull final InstallSource installSource;
final String volumeUuid;
private boolean mVerificationCompleted;
+ private boolean mIntegrityVerificationCompleted;
private boolean mEnableRollbackCompleted;
private InstallArgs mArgs;
int mRet;
@@ -14112,155 +14220,30 @@
final InstallArgs args = createInstallArgs(this);
mVerificationCompleted = true;
+ mIntegrityVerificationCompleted = true;
mEnableRollbackCompleted = true;
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
- // TODO: http://b/22976637
- // Apps installed for "all" users use the device owner to verify the app
- UserHandle verifierUser = getUser();
- if (verifierUser == UserHandle.ALL) {
- verifierUser = UserHandle.SYSTEM;
- }
+ final int verificationId = mPendingVerificationToken++;
- /*
- * Determine if we have any installed package verifiers. If we
- * do, then we'll defer to them to verify the packages.
- */
- final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
- verifierUser.getIdentifier());
- final int installerUid =
- verificationInfo == null ? -1 : verificationInfo.installerUid;
- if (!origin.existing && requiredUid != -1
- && isVerificationEnabled(
- verifierUser.getIdentifier(), installFlags, installerUid)) {
- final Intent verification = new Intent(
- Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
- PACKAGE_MIME_TYPE);
- verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Query all live verifiers based on current user state
- final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
- PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
- false /*allowDynamicSplits*/);
-
- if (DEBUG_VERIFY) {
- Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
- + verification.toString() + " with " + pkgLite.verifiers.length
- + " optional verifiers");
- }
-
- final int verificationId = mPendingVerificationToken++;
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
- installSource.initiatingPackageName);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
- installFlags);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
- pkgLite.packageName);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
- pkgLite.versionCode);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
- pkgLite.getLongVersionCode());
-
- if (verificationInfo != null) {
- if (verificationInfo.originatingUri != null) {
- verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
- verificationInfo.originatingUri);
- }
- if (verificationInfo.referrer != null) {
- verification.putExtra(Intent.EXTRA_REFERRER,
- verificationInfo.referrer);
- }
- if (verificationInfo.originatingUid >= 0) {
- verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
- verificationInfo.originatingUid);
- }
- if (verificationInfo.installerUid >= 0) {
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
- verificationInfo.installerUid);
- }
- }
-
- final PackageVerificationState verificationState = new PackageVerificationState(
- requiredUid, this);
-
+ // Perform package verification (unless we are simply moving the package).
+ if (!origin.existing) {
+ PackageVerificationState verificationState =
+ new PackageVerificationState(this);
mPendingVerification.append(verificationId, verificationState);
- final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
- receivers, verificationState);
+ sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
+ ret = sendPackageVerificationRequest(
+ verificationId, pkgLite, verificationState);
- DeviceIdleInternal idleController =
- mInjector.getLocalDeviceIdleController();
- final long idleDuration = getVerificationTimeout();
-
- /*
- * If any sufficient verifiers were listed in the package
- * manifest, attempt to ask them.
- */
- if (sufficientVerifiers != null) {
- final int N = sufficientVerifiers.size();
- if (N == 0) {
- Slog.i(TAG, "Additional verifiers required, but none installed.");
- ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
- } else {
- for (int i = 0; i < N; i++) {
- final ComponentName verifierComponent = sufficientVerifiers.get(i);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- verifierComponent.getPackageName(), idleDuration,
- verifierUser.getIdentifier(), false, "package verifier");
-
- final Intent sufficientIntent = new Intent(verification);
- sufficientIntent.setComponent(verifierComponent);
- mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
- }
- }
- }
-
- final ComponentName requiredVerifierComponent = matchComponentForVerifier(
- mRequiredVerifierPackage, receivers);
- if (ret == PackageManager.INSTALL_SUCCEEDED
- && mRequiredVerifierPackage != null) {
- Trace.asyncTraceBegin(
- TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
- /*
- * Send the intent to the required verification agent,
- * but only start the verification timeout after the
- * target BroadcastReceivers have run.
- */
- verification.setComponent(requiredVerifierComponent);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- mRequiredVerifierPackage, idleDuration,
- verifierUser.getIdentifier(), false, "package verifier");
- mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
- android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Message msg = mHandler
- .obtainMessage(CHECK_PENDING_VERIFICATION);
- msg.arg1 = verificationId;
- mHandler.sendMessageDelayed(msg, getVerificationTimeout());
- }
- }, null, 0, null, null);
-
- /*
- * We don't want the copy to proceed until verification
- * succeeds.
- */
- mVerificationCompleted = false;
+ // If both verifications are skipped, we should remove the state.
+ if (verificationState.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
}
}
+
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// TODO(ruhler) b/112431924: Don't do this in case of 'move'?
final int enableRollbackToken = mPendingEnableRollbackToken++;
@@ -14316,6 +14299,228 @@
mRet = ret;
}
+ /**
+ * Send a request to check the integrity of the package.
+ */
+ void sendIntegrityVerificationRequest(
+ int verificationId,
+ PackageInfoLite pkgLite,
+ PackageVerificationState verificationState) {
+ if (!isIntegrityVerificationEnabled()) {
+ // Consider the integrity check as passed.
+ verificationState.setIntegrityVerificationResult(
+ PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ return;
+ }
+
+ final Intent integrityVerification =
+ new Intent(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+
+ integrityVerification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
+
+ final int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND;
+ integrityVerification.addFlags(flags);
+
+ integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
+ integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
+ integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
+ populateInstallerExtras(integrityVerification);
+
+ // send to integrity component only.
+ integrityVerification.setPackage("android");
+
+ DeviceIdleInternal idleController =
+ mInjector.getLocalDeviceIdleController();
+ final long idleDuration = getVerificationTimeout();
+
+ idleController.addPowerSaveTempWhitelistAppDirect(Process.myUid(),
+ idleDuration,
+ false, "integrity component");
+ mContext.sendOrderedBroadcastAsUser(integrityVerification, UserHandle.SYSTEM,
+ /* receiverPermission= */ null,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg =
+ mHandler.obtainMessage(CHECK_PENDING_INTEGRITY_VERIFICATION);
+ msg.arg1 = verificationId;
+ // TODO: do we want to use the same timeout?
+ mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+ }
+ }, /* scheduler= */ null,
+ /* initialCode= */ 0,
+ /* initialData= */ null,
+ /* initialExtras= */ null);
+
+ Trace.asyncTraceBegin(
+ TRACE_TAG_PACKAGE_MANAGER, "integrity_verification", verificationId);
+
+ // stop the copy until verification succeeds.
+ mIntegrityVerificationCompleted = false;
+ }
+
+ /**
+ * Send a request to verifier(s) to verify the package if necessary, and return
+ * {@link PackageManager#INSTALL_SUCCEEDED} if succeeded.
+ */
+ int sendPackageVerificationRequest(
+ int verificationId,
+ PackageInfoLite pkgLite,
+ PackageVerificationState verificationState) {
+ int ret = INSTALL_SUCCEEDED;
+
+ // TODO: http://b/22976637
+ // Apps installed for "all" users use the device owner to verify the app
+ UserHandle verifierUser = getUser();
+ if (verifierUser == UserHandle.ALL) {
+ verifierUser = UserHandle.SYSTEM;
+ }
+
+ /*
+ * Determine if we have any installed package verifiers. If we
+ * do, then we'll defer to them to verify the packages.
+ */
+ final int requiredUid = mRequiredVerifierPackage == null ? -1
+ : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+ verifierUser.getIdentifier());
+ verificationState.setRequiredVerifierUid(requiredUid);
+ final int installerUid =
+ verificationInfo == null ? -1 : verificationInfo.installerUid;
+ if (!origin.existing && requiredUid != -1
+ && isVerificationEnabled(
+ verifierUser.getIdentifier(), installFlags, installerUid)) {
+ final Intent verification = new Intent(
+ Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
+ verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Query all live verifiers based on current user state
+ final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
+ PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
+ false /*allowDynamicSplits*/);
+
+ if (DEBUG_VERIFY) {
+ Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
+ + verification.toString() + " with " + pkgLite.verifiers.length
+ + " optional verifiers");
+ }
+
+ verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, installFlags);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
+ pkgLite.getLongVersionCode());
+
+ populateInstallerExtras(verification);
+
+ final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
+ receivers, verificationState);
+
+ DeviceIdleInternal idleController =
+ mInjector.getLocalDeviceIdleController();
+ final long idleDuration = getVerificationTimeout();
+
+ /*
+ * If any sufficient verifiers were listed in the package
+ * manifest, attempt to ask them.
+ */
+ if (sufficientVerifiers != null) {
+ final int n = sufficientVerifiers.size();
+ if (n == 0) {
+ Slog.i(TAG, "Additional verifiers required, but none installed.");
+ ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
+ } else {
+ for (int i = 0; i < n; i++) {
+ final ComponentName verifierComponent = sufficientVerifiers.get(i);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ verifierComponent.getPackageName(), idleDuration,
+ verifierUser.getIdentifier(), false, "package verifier");
+
+ final Intent sufficientIntent = new Intent(verification);
+ sufficientIntent.setComponent(verifierComponent);
+ mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
+ }
+ }
+ }
+
+ final ComponentName requiredVerifierComponent = matchComponentForVerifier(
+ mRequiredVerifierPackage, receivers);
+ if (mRequiredVerifierPackage != null) {
+ /*
+ * Send the intent to the required verification agent,
+ * but only start the verification timeout after the
+ * target BroadcastReceivers have run.
+ */
+ verification.setComponent(requiredVerifierComponent);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ mRequiredVerifierPackage, idleDuration,
+ verifierUser.getIdentifier(), false, "package verifier");
+ mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
+ android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg = mHandler
+ .obtainMessage(CHECK_PENDING_VERIFICATION);
+ msg.arg1 = verificationId;
+ mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+ }
+ }, null, 0, null, null);
+
+ Trace.asyncTraceBegin(
+ TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
+ /*
+ * We don't want the copy to proceed until verification
+ * succeeds.
+ */
+ mVerificationCompleted = false;
+ }
+ } else {
+ verificationState.setVerifierResponse(
+ requiredUid, PackageManager.VERIFICATION_ALLOW);
+ }
+ return ret;
+ }
+
+ void populateInstallerExtras(Intent intent) {
+ intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
+ installSource.initiatingPackageName);
+
+ if (verificationInfo != null) {
+ if (verificationInfo.originatingUri != null) {
+ intent.putExtra(Intent.EXTRA_ORIGINATING_URI,
+ verificationInfo.originatingUri);
+ }
+ if (verificationInfo.referrer != null) {
+ intent.putExtra(Intent.EXTRA_REFERRER,
+ verificationInfo.referrer);
+ }
+ if (verificationInfo.originatingUid >= 0) {
+ intent.putExtra(Intent.EXTRA_ORIGINATING_UID,
+ verificationInfo.originatingUid);
+ }
+ if (verificationInfo.installerUid >= 0) {
+ intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
+ verificationInfo.installerUid);
+ }
+ }
+ }
+
void setReturnCode(int ret) {
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
// Only update mRet if it was previously INSTALL_SUCCEEDED to
@@ -14325,10 +14530,28 @@
}
void handleVerificationFinished() {
- mVerificationCompleted = true;
- handleReturnCode();
+ if (!mVerificationCompleted) {
+ mVerificationCompleted = true;
+ if (mIntegrityVerificationCompleted || mRet != INSTALL_SUCCEEDED) {
+ mIntegrityVerificationCompleted = true;
+ handleReturnCode();
+ }
+ // integrity verification still pending.
+ }
}
+ void handleIntegrityVerificationFinished() {
+ if (!mIntegrityVerificationCompleted) {
+ mIntegrityVerificationCompleted = true;
+ if (mVerificationCompleted || mRet != INSTALL_SUCCEEDED) {
+ mVerificationCompleted = true;
+ handleReturnCode();
+ }
+ // verifier still pending
+ }
+ }
+
+
void handleRollbackEnabled() {
// TODO(ruhler) b/112431924: Consider halting the install if we
// couldn't enable rollback.
@@ -14338,7 +14561,8 @@
@Override
void handleReturnCode() {
- if (mVerificationCompleted && mEnableRollbackCompleted) {
+ if (mVerificationCompleted
+ && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
String packageName = "";
try {
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index c50bf59..ea7af90 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -22,18 +22,17 @@
import com.android.server.pm.PackageManagerService.InstallParams;
/**
- * Tracks the package verification state for a particular package. Each package
- * verification has a required verifier and zero or more sufficient verifiers.
- * Only one of the sufficient verifier list must return affirmative to allow the
- * package to be considered verified. If there are zero sufficient verifiers,
- * then package verification is considered complete.
+ * Tracks the package verification state for a particular package. Each package verification has a
+ * required verifier and zero or more sufficient verifiers. Only one of the sufficient verifier list
+ * must return affirmative to allow the package to be considered verified. If there are zero
+ * sufficient verifiers, then package verification is considered complete.
*/
class PackageVerificationState {
private final InstallParams mParams;
private final SparseBooleanArray mSufficientVerifierUids;
- private final int mRequiredVerifierUid;
+ private int mRequiredVerifierUid;
private boolean mSufficientVerificationComplete;
@@ -45,16 +44,13 @@
private boolean mExtendedTimeout;
+ private boolean mIntegrityVerificationComplete;
+
/**
- * Create a new package verification state where {@code requiredVerifierUid}
- * is the user ID for the package that must reply affirmative before things
- * can continue.
- *
- * @param requiredVerifierUid user ID of required package verifier
- * @param args
+ * Create a new package verification state where {@code requiredVerifierUid} is the user ID for
+ * the package that must reply affirmative before things can continue.
*/
- PackageVerificationState(int requiredVerifierUid, InstallParams params) {
- mRequiredVerifierUid = requiredVerifierUid;
+ PackageVerificationState(InstallParams params) {
mParams = params;
mSufficientVerifierUids = new SparseBooleanArray();
mExtendedTimeout = false;
@@ -64,6 +60,11 @@
return mParams;
}
+ /** Sets the user ID of the required package verifier. */
+ void setRequiredVerifierUid(int uid) {
+ mRequiredVerifierUid = uid;
+ }
+
/**
* Add a verifier which is added to our sufficient list.
*
@@ -74,8 +75,8 @@
}
/**
- * Should be called when a verification is received from an agent so the
- * state of the package verification can be tracked.
+ * Should be called when a verification is received from an agent so the state of the package
+ * verification can be tracked.
*
* @param uid user ID of the verifying agent
* @return {@code true} if the verifying agent actually exists in our list
@@ -114,9 +115,8 @@
}
/**
- * Returns whether verification is considered complete. This means that the
- * required verifier and at least one of the sufficient verifiers has
- * returned a positive verification.
+ * Returns whether verification is considered complete. This means that the required verifier
+ * and at least one of the sufficient verifiers has returned a positive verification.
*
* @return {@code true} when verification is considered complete
*/
@@ -133,8 +133,8 @@
}
/**
- * Returns whether installation should be allowed. This should only be
- * called after {@link #isVerificationComplete()} returns {@code true}.
+ * Returns whether installation should be allowed. This should only be called after {@link
+ * #isVerificationComplete()} returns {@code true}.
*
* @return {@code true} if installation should be allowed
*/
@@ -150,9 +150,7 @@
return true;
}
- /**
- * Extend the timeout for this Package to be verified.
- */
+ /** Extend the timeout for this Package to be verified. */
void extendTimeout() {
if (!mExtendedTimeout) {
mExtendedTimeout = true;
@@ -167,4 +165,16 @@
boolean timeoutExtended() {
return mExtendedTimeout;
}
+
+ void setIntegrityVerificationResult(int code) {
+ mIntegrityVerificationComplete = true;
+ }
+
+ boolean isIntegrityVerificationComplete() {
+ return mIntegrityVerificationComplete;
+ }
+
+ boolean areAllVerificationsComplete() {
+ return mIntegrityVerificationComplete && isVerificationComplete();
+ }
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fd95ac5..45c012e 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1881,7 +1881,10 @@
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
|| inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
- if (insideParentBounds && mStack != null) {
+ if (insideParentBounds && WindowConfiguration.isFloating(windowingMode)) {
+ mTmpNonDecorBounds.set(mTmpFullBounds);
+ mTmpStableBounds.set(mTmpFullBounds);
+ } else if (insideParentBounds && mStack != null) {
final DisplayInfo di = new DisplayInfo();
mStack.getDisplay().mDisplay.getDisplayInfo(di);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index 37ff06a..c080332 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -16,12 +16,6 @@
package com.android.server.integrity;
-import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
-
-import static org.mockito.Mockito.verify;
-
-import android.content.Intent;
-import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import androidx.test.InstrumentationRegistry;
@@ -56,17 +50,7 @@
}
@Test
- public void integrityVerification_allow() {
- int verificationId = 2;
- Intent integrityVerificationIntent = new Intent();
- integrityVerificationIntent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
- integrityVerificationIntent.putExtra(EXTRA_VERIFICATION_ID, verificationId);
-
- // We cannot send the broadcast using the context since it is a protected broadcast and
- // we will get a security exception.
- mService.handleIntegrityVerification(integrityVerificationIntent);
-
- verify(mPackageManagerInternal)
- .setIntegrityVerificationResult(verificationId, PackageManager.VERIFICATION_ALLOW);
+ public void noop() {
+ // We need this test just as a place holder since an empty test suite is treated as error.
}
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index ad74901..0bb2d44 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -44,48 +44,66 @@
@RunWith(JUnit4.class)
public class RuleXmlSerializerTest {
+ private static final String SAMPLE_INSTALLER_NAME = "com.test.installer";
+ private static final String SAMPLE_INSTALLER_CERT = "installer_cert";
+
@Test
- public void testXmlString_serializeEmptyRule() throws Exception {
- Rule rule = null;
+ public void testXmlString_serializeEmptyRuleList() throws Exception {
RuleSerializer xmlSerializer = new RuleXmlSerializer();
String expectedRules = "<RL />";
byte[] actualRules =
xmlSerializer.serialize(
- Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
+ Collections.emptyList(), /* formatVersion= */ Optional.empty());
assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
- public void testXmlString_serializeMultipleRules_oneEmpty() throws Exception {
- Rule rule1 = null;
- Rule rule2 =
+ public void testXmlString_serializeMultipleRules_indexingOrderPreserved() throws Exception {
+ String packageNameA = "aaa";
+ String packageNameB = "bbb";
+ String packageNameC = "ccc";
+ String appCert1 = "cert1";
+ String appCert2 = "cert2";
+ String appCert3 = "cert3";
+ Rule installerRule =
new Rule(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME,
- "com.app.test",
- /* isHashedValue= */ false),
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_CERTIFICATE,
+ SAMPLE_INSTALLER_CERT,
+ /* isHashedValue= */ false))),
Rule.DENY);
- RuleSerializer xmlSerializer = new RuleXmlSerializer();
- Map<String, String> packageNameAttrs = new LinkedHashMap<>();
- packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
- packageNameAttrs.put("V", "com.app.test");
- packageNameAttrs.put("H", "false");
- String expectedRules =
- "<RL>"
- + generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ RuleSerializer xmlSerializer = new RuleXmlSerializer();
byte[] actualRules =
xmlSerializer.serialize(
- Arrays.asList(rule1, rule2), /* formatVersion= */ Optional.empty());
+ Arrays.asList(
+ installerRule,
+ getRuleWithAppCertificateAndSampleInstallerName(appCert1),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameB),
+ getRuleWithAppCertificateAndSampleInstallerName(appCert3),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameC),
+ getRuleWithAppCertificateAndSampleInstallerName(appCert2),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameA)),
+ /* formatVersion= */ Optional.empty());
+
+ String expectedRules = "<RL>"
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameA)
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameB)
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameC)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert1)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert2)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert3)
+ + getSerializedCompoundRuleWithSampleInstallerNameAndCert()
+ + "</RL>";
assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@@ -371,7 +389,7 @@
assertExpectException(
RuleSerializeException.class,
- /* expectedExceptionMessageRegex */ "Invalid formula type",
+ /* expectedExceptionMessageRegex */ "Malformed rule identified.",
() ->
xmlSerializer.serialize(
Collections.singletonList(rule),
@@ -393,6 +411,124 @@
return res.toString();
}
+ private Rule getRuleWithPackageNameAndSampleInstallerName(String packageName) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ String packageName) {
+
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", packageName);
+ packageNameAttrs.put("H", "false");
+
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
+
+ private Rule getRuleWithAppCertificateAndSampleInstallerName(String certificate) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ certificate,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(
+ String appCert) {
+
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
+ packageNameAttrs.put("V", appCert);
+ packageNameAttrs.put("H", "false");
+
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
+ private String getSerializedCompoundRuleWithSampleInstallerNameAndCert() {
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ Map<String, String> installerCertAttrs = new LinkedHashMap<>();
+ installerCertAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_CERTIFICATE));
+ installerCertAttrs.put("V", SAMPLE_INSTALLER_CERT);
+ installerCertAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerCertAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
private Formula getInvalidFormula() {
return new Formula() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
index ebd3633..1fff4f0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -17,8 +17,7 @@
package com.android.server.pm;
import android.content.pm.PackageManager;
-import com.android.server.pm.PackageVerificationState;
-
+import android.content.pm.PackageManagerInternal;
import android.test.AndroidTestCase;
public class PackageVerificationStateTest extends AndroidTestCase {
@@ -29,7 +28,8 @@
private static final int SUFFICIENT_UID_2 = 8938;
public void testPackageVerificationState_OnlyRequiredVerifier_AllowedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -44,7 +44,8 @@
}
public void testPackageVerificationState_OnlyRequiredVerifier_DeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -59,7 +60,8 @@
}
public void testPackageVerificationState_RequiredAndOneSufficient_RequiredDeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -84,7 +86,8 @@
}
public void testPackageVerificationState_RequiredAndOneSufficient_SufficientDeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -109,7 +112,8 @@
}
public void testPackageVerificationState_RequiredAndTwoSufficient_OneSufficientIsEnough() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -135,7 +139,8 @@
}
public void testPackageVerificationState_RequiredAndTwoSufficient_SecondSufficientIsEnough() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -166,7 +171,8 @@
}
public void testPackageVerificationState_RequiredAndTwoSufficient_RequiredOverrides() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -202,4 +208,55 @@
assertTrue("Installation should be marked as allowed still",
state.isInstallAllowed());
}
+
+ public void testAreAllVerificationsComplete_onlyVerificationPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyIntegrityCheckPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_bothPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+ assertTrue(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyVerificationFails() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyIntegrityCheckFails() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 1a18df5..de6d752 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -427,6 +427,61 @@
assertNotEquals(origScreenH, task.getConfiguration().screenHeightDp);
}
+ @Test
+ public void testInsetDisregardedWhenFreeformOverlapsNavBar() {
+ DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ DisplayInfo displayInfo = new DisplayInfo();
+ mService.mContext.getDisplay().getDisplayInfo(displayInfo);
+ final int displayHeight = displayInfo.logicalHeight;
+ final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
+ final Configuration inOutConfig = new Configuration();
+ final Configuration parentConfig = new Configuration();
+ final int longSide = 1200;
+ final int shortSide = 600;
+ parentConfig.densityDpi = 400;
+ parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px
+ parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
+ parentConfig.windowConfiguration.setRotation(ROTATION_0);
+
+ final float density = 2.5f; // densityDpi / DENSITY_DEFAULT_SCALE = 400 / 160.0f
+ final int longSideDp = 480; // longSide / density = 1200 / 400 * 160
+ final int shortSideDp = 240; // shortSide / density = 600 / 400 * 160
+ final int screenLayout = parentConfig.screenLayout
+ & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
+ final int reducedScreenLayout =
+ Configuration.reduceScreenLayout(screenLayout, longSideDp, shortSideDp);
+
+ // Portrait bounds overlapping with navigation bar, without insets.
+ inOutConfig.windowConfiguration.getBounds().set(0,
+ displayHeight - 10 - longSide,
+ shortSide,
+ displayHeight - 10);
+ // Set to freeform mode to verify bug fix.
+ inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
+ assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
+
+ inOutConfig.setToDefaults();
+ // Landscape bounds overlapping with navigtion bar, without insets.
+ inOutConfig.windowConfiguration.getBounds().set(0,
+ displayHeight - 10 - shortSide,
+ longSide,
+ displayHeight - 10);
+ inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
+ assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
+ }
+
/** Ensures that the alias intent won't have target component resolved. */
@Test
public void testTaskIntentActivityAlias() {
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 3940a3b..9b9997f 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -485,6 +485,86 @@
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING})
public @interface PreciseCallStates {}
+ @IntDef(value = {
+ DisconnectCause.NOT_VALID,
+ DisconnectCause.NOT_DISCONNECTED,
+ DisconnectCause.INCOMING_MISSED,
+ DisconnectCause.NORMAL,
+ DisconnectCause.LOCAL,
+ DisconnectCause.BUSY,
+ DisconnectCause.CONGESTION,
+ DisconnectCause.MMI,
+ DisconnectCause.INVALID_NUMBER,
+ DisconnectCause.NUMBER_UNREACHABLE,
+ DisconnectCause.SERVER_UNREACHABLE,
+ DisconnectCause.INVALID_CREDENTIALS,
+ DisconnectCause.OUT_OF_NETWORK,
+ DisconnectCause.SERVER_ERROR,
+ DisconnectCause.TIMED_OUT,
+ DisconnectCause.LOST_SIGNAL,
+ DisconnectCause.LIMIT_EXCEEDED,
+ DisconnectCause.INCOMING_REJECTED,
+ DisconnectCause.POWER_OFF,
+ DisconnectCause.OUT_OF_SERVICE,
+ DisconnectCause.ICC_ERROR,
+ DisconnectCause.CALL_BARRED,
+ DisconnectCause.FDN_BLOCKED,
+ DisconnectCause.CS_RESTRICTED,
+ DisconnectCause.CS_RESTRICTED_NORMAL,
+ DisconnectCause.CS_RESTRICTED_EMERGENCY,
+ DisconnectCause.UNOBTAINABLE_NUMBER,
+ DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+ DisconnectCause.CDMA_DROP,
+ DisconnectCause.CDMA_INTERCEPT,
+ DisconnectCause.CDMA_REORDER,
+ DisconnectCause.CDMA_SO_REJECT,
+ DisconnectCause.CDMA_RETRY_ORDER,
+ DisconnectCause.CDMA_ACCESS_FAILURE,
+ DisconnectCause.CDMA_PREEMPTED,
+ DisconnectCause.CDMA_NOT_EMERGENCY,
+ DisconnectCause.CDMA_ACCESS_BLOCKED,
+ DisconnectCause.ERROR_UNSPECIFIED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DisconnectCauses {
+ }
+
+ @IntDef(value = {
+ PreciseDisconnectCause.NOT_VALID,
+ PreciseDisconnectCause.NO_DISCONNECT_CAUSE_AVAILABLE,
+ PreciseDisconnectCause.UNOBTAINABLE_NUMBER,
+ PreciseDisconnectCause.NORMAL,
+ PreciseDisconnectCause.BUSY,
+ PreciseDisconnectCause.NUMBER_CHANGED,
+ PreciseDisconnectCause.STATUS_ENQUIRY,
+ PreciseDisconnectCause.NORMAL_UNSPECIFIED,
+ PreciseDisconnectCause.NO_CIRCUIT_AVAIL,
+ PreciseDisconnectCause.TEMPORARY_FAILURE,
+ PreciseDisconnectCause.SWITCHING_CONGESTION,
+ PreciseDisconnectCause.CHANNEL_NOT_AVAIL,
+ PreciseDisconnectCause.QOS_NOT_AVAIL,
+ PreciseDisconnectCause.BEARER_NOT_AVAIL,
+ PreciseDisconnectCause.ACM_LIMIT_EXCEEDED,
+ PreciseDisconnectCause.CALL_BARRED,
+ PreciseDisconnectCause.FDN_BLOCKED,
+ PreciseDisconnectCause.IMSI_UNKNOWN_IN_VLR,
+ PreciseDisconnectCause.IMEI_NOT_ACCEPTED,
+ PreciseDisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+ PreciseDisconnectCause.CDMA_DROP,
+ PreciseDisconnectCause.CDMA_INTERCEPT,
+ PreciseDisconnectCause.CDMA_REORDER,
+ PreciseDisconnectCause.CDMA_SO_REJECT,
+ PreciseDisconnectCause.CDMA_RETRY_ORDER,
+ PreciseDisconnectCause.CDMA_ACCESS_FAILURE,
+ PreciseDisconnectCause.CDMA_PREEMPTED,
+ PreciseDisconnectCause.CDMA_NOT_EMERGENCY,
+ PreciseDisconnectCause.CDMA_ACCESS_BLOCKED,
+ PreciseDisconnectCause.ERROR_UNSPECIFIED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PreciseDisconnectCauses {
+ }
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = {
ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index b7dab16..e523fba 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -19,6 +19,7 @@
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -181,7 +182,8 @@
* @return a CellLocation object for this CellIdentity
* @hide
*/
- public abstract CellLocation asCellLocation();
+ @SystemApi
+ public abstract @NonNull CellLocation asCellLocation();
@Override
public boolean equals(Object other) {
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 880d3db..54236b42 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.telephony.cdma.CdmaCellLocation;
@@ -198,6 +199,7 @@
}
/** @hide */
+ @NonNull
@Override
public CdmaCellLocation asCellLocation() {
CdmaCellLocation cl = new CdmaCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 25c6577..4e4454d 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
@@ -200,6 +201,7 @@
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 997b19f..c3fc73b 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
@@ -232,6 +233,7 @@
*
* @hide
*/
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index edc838c..e3fec7b 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
@@ -77,6 +78,7 @@
* @return a CellLocation object for this CellIdentity.
* @hide
*/
+ @NonNull
@Override
public CellLocation asCellLocation() {
return new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 558e346..8f812b6 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -171,6 +171,7 @@
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 031fed1..556bc32 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
@@ -196,6 +197,7 @@
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index 9f75332..bfa6326 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -16,19 +16,18 @@
package android.telephony;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.PreciseCallStates;
+import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.DisconnectCause;
import android.telephony.PreciseDisconnectCause;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -73,19 +72,26 @@
private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
private @PreciseCallStates int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
- private int mDisconnectCause = DisconnectCause.NOT_VALID;
- private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+ private @DisconnectCauses int mDisconnectCause = DisconnectCause.NOT_VALID;
+ private @PreciseDisconnectCauses int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
/**
- * Constructor
+ * Construct PreciseCallState with parameters
+ *
+ * @param ringingCall ring call state
+ * @param foregroundCall foreground call state
+ * @param backgroundCall background call state
+ * @param disconnectCause disconnect cause
+ * @param preciseDisconnectCause precise disconnect cause
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public PreciseCallState(@PreciseCallStates int ringingCall,
@PreciseCallStates int foregroundCall,
- @PreciseCallStates int backgroundCall, int disconnectCause,
- int preciseDisconnectCause) {
+ @PreciseCallStates int backgroundCall,
+ @DisconnectCauses int disconnectCause,
+ @PreciseDisconnectCauses int preciseDisconnectCause) {
mRingingCallState = ringingCall;
mForegroundCallState = foregroundCall;
mBackgroundCallState = backgroundCall;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 60fda09..a96325e 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1950,14 +1950,9 @@
return null;
}
- Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName(),
+ CellIdentity cellIdentity = telephony.getCellLocation(mContext.getOpPackageName(),
mContext.getFeatureId());
- if (bundle == null || bundle.isEmpty()) {
- Rlog.d(TAG, "getCellLocation returning null because CellLocation is unavailable");
- return null;
- }
-
- CellLocation cl = CellLocation.newFromBundle(bundle);
+ CellLocation cl = cellIdentity.asCellLocation();
if (cl == null || cl.isEmpty()) {
Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty or"
+ " phone type doesn't match CellLocation type");
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 97b24ae..0baac71 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -30,6 +30,7 @@
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierRestrictionRules;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ClientRequestStats;
import android.telephony.IccOpenLogicalChannelResponse;
@@ -305,7 +306,8 @@
*/
boolean isDataConnectivityPossible(int subId);
- Bundle getCellLocation(String callingPkg, String callingFeatureId);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ CellIdentity getCellLocation(String callingPkg, String callingFeatureId);
/**
* Returns the ISO country code equivalent of the current registered