diff options
44 files changed, 1266 insertions, 321 deletions
diff --git a/api/current.txt b/api/current.txt index 86aa80b159bd..94a913d82fe1 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3955,6 +3955,7 @@ package android.app { 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 05e2ca57221f..c0f8ceb1b601 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8981,6 +8981,34 @@ package android.telephony { 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 @@ package android.telephony { } 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 68bdfae218ae..3f9f7fbbe477 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -4547,4 +4547,17 @@ public class ActivityManager { 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 112bd303a8b3..e8494c4c5893 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -583,4 +583,9 @@ interface IActivityManager { * 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 c5a147af3137..7967708ce19a 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -11050,6 +11050,7 @@ public class Intent implements Parcelable, Cloneable { 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 51a9c864ee29..e5f2c3afa247 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -24,7 +24,6 @@ import android.annotation.TestApi; 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 @@ public class PhoneStateListener { () -> 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 f574160e5303..1b2fedad842e 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -22,7 +22,6 @@ import android.annotation.SystemApi; 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 @@ public class TelephonyRegistryManager { } /** - * 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 cb67309ce74f..6c7e3dc84425 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 @@ oneway interface IPhoneStateListener { 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 @@ oneway interface IPhoneStateListener { 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 f954679ebf4d..4e405037f6ef 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -19,8 +19,8 @@ package com.android.internal.telephony; 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 @@ interface ITelephonyRegistry { 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 000000000000..e12c715a2a32 --- /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 c692a2625199..e918268fa073 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 fdb6bbb4550b..636f4c8b59ca 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 @@ package com.android.overlaytest; 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 @@ import java.util.Locale; @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 @@ public abstract class OverlayBaseTest { @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 @@ public abstract class OverlayBaseTest { 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 000000000000..2245e2b8121b --- /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 7d2840886683..873ca3c9b821 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 000000000000..7b636054c936 --- /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 972137a3d1bf..74c496386f2f 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 000000000000..38e5fa18300c --- /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 ce3bffff0aa5..0b2fd9ec982d 100644 --- a/libs/androidfw/Idmap.cpp +++ b/libs/androidfw/Idmap.cpp @@ -57,7 +57,7 @@ OverlayStringPool::~OverlayStringPool() { 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 char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const { 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 ab4c9c204842..ccb57f373473 100644 --- a/libs/androidfw/include/androidfw/Idmap.h +++ b/libs/androidfw/include/androidfw/Idmap.h @@ -40,8 +40,9 @@ class IdmapResMap; 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 @@ class OverlayStringPool : public ResStringPool { // 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 b603326cec34..35cebd425dc7 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -520,7 +520,7 @@ public: 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 f363a73b05af..40a7dfcfc18d 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -67,6 +67,27 @@ public abstract class PackageManagerInternal { 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 @@ public abstract class PackageManagerInternal { * {@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 13eb55665741..46ff71831905 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.RadioPowerState; 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { // 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { int numPhones = getTelephonyManager().getPhoneCount(); for (int sub = 0; sub < numPhones; sub++) { TelephonyRegistry.this.notifyCellLocationForSubscriber(sub, - mCellLocation[sub]); + mCellIdentity[sub]); } break; } @@ -404,7 +405,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { 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 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + /** 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 6dc49b7ba375..d7a46fec7767 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 @@ public class ActivityManagerService extends IActivityManager.Stub }); } + @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 0b74840d850b..9f23cdaf3b86 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 @@ public class AppOpsService extends IAppOpsService.Stub { } 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 39c1b8535565..5c4479a1a2fe 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.BroadcastReceiver; 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 @@ import com.android.server.LocalServices; 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 @@ class AppIntegrityManagerServiceImpl { 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 @@ class AppIntegrityManagerServiceImpl { 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 cfe50c6c8ac9..ebf6a2e20238 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.OutputStream; 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 @@ public class RuleXmlSerializer implements RuleSerializer { } } - 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 1a6416638407..785ca7dd1fe8 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.Manifest.permission.WRITE_EXTERNAL_STORAGE; 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 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE); } + if (state.areAllVerificationsComplete()) { + mPendingVerification.remove(verificationId); + } + Trace.asyncTraceEnd( TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId); @@ -1773,7 +1829,40 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub } /** + * 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 @@ public class PackageManagerService extends IPackageManager.Stub } } + /** + * 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 @@ public class PackageManagerService extends IPackageManager.Stub @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 @@ public class PackageManagerService extends IPackageManager.Stub 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; - } - - /* - * 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); + final int verificationId = mPendingVerificationToken++; + // 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); - - DeviceIdleInternal idleController = - mInjector.getLocalDeviceIdleController(); - final long idleDuration = getVerificationTimeout(); + sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState); + ret = sendPackageVerificationRequest( + verificationId, pkgLite, verificationState); - /* - * 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 @@ public class PackageManagerService extends IPackageManager.Stub 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 @@ public class PackageManagerService extends IPackageManager.Stub } 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 @@ public class PackageManagerService extends IPackageManager.Stub @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 c50bf59f0206..ea7af9031bd0 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 android.util.SparseBooleanArray; 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 @@ class PackageVerificationState { 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 @@ class PackageVerificationState { 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 @@ class PackageVerificationState { } /** - * 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 @@ class PackageVerificationState { } /** - * 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 @@ class PackageVerificationState { } /** - * 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 @@ class PackageVerificationState { 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 @@ class PackageVerificationState { 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 fd95ac500370..45c012e6cd86 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 @@ class Task extends WindowContainer<WindowContainer> { 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 37ff06a18492..c080332ca281 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 @@ public class AppIntegrityManagerServiceImplTest { } @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 ad74901ece2c..0bb2d4489b6b 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 @@ import java.util.Optional; @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 @@ public class RuleXmlSerializerTest { assertExpectException( RuleSerializeException.class, - /* expectedExceptionMessageRegex */ "Invalid formula type", + /* expectedExceptionMessageRegex */ "Malformed rule identified.", () -> xmlSerializer.serialize( Collections.singletonList(rule), @@ -393,6 +411,124 @@ public class RuleXmlSerializerTest { 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 ebd363386fa3..1fff4f084fc4 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 @@ public class PackageVerificationStateTest extends AndroidTestCase { 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 class PackageVerificationStateTest extends AndroidTestCase { } 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 class PackageVerificationStateTest extends AndroidTestCase { } 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 class PackageVerificationStateTest extends AndroidTestCase { } 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 class PackageVerificationStateTest extends AndroidTestCase { } 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 class PackageVerificationStateTest extends AndroidTestCase { } 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 class PackageVerificationStateTest extends AndroidTestCase { } 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 @@ public class PackageVerificationStateTest extends AndroidTestCase { 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 1a18df5b6fcf..de6d75235777 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 @@ public class TaskRecordTests extends ActivityTestsBase { 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 3940a3b0a1cf..9b9997f9b737 100644 --- a/telephony/java/android/telephony/Annotation.java +++ b/telephony/java/android/telephony/Annotation.java @@ -485,6 +485,86 @@ public class Annotation { 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 b7dab161c331..e523fbab2bb0 100644 --- a/telephony/java/android/telephony/CellIdentity.java +++ b/telephony/java/android/telephony/CellIdentity.java @@ -19,6 +19,7 @@ package android.telephony; 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 @@ public abstract class CellIdentity implements Parcelable { * @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 880d3db681b5..54236b426d98 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 @@ public final class CellIdentityCdma extends CellIdentity { } /** @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 25c6577bdcf5..4e4454d6a1c2 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 @@ public final class CellIdentityGsm extends CellIdentity { } /** @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 997b19f3d4eb..c3fc73b775d7 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 @@ public final class CellIdentityLte extends CellIdentity { * * @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 edc838c163db..e3fec7b7f820 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 @@ public final class CellIdentityNr extends CellIdentity { * @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 558e346284ea..8f812b6b892e 100644 --- a/telephony/java/android/telephony/CellIdentityTdscdma.java +++ b/telephony/java/android/telephony/CellIdentityTdscdma.java @@ -171,6 +171,7 @@ public final class CellIdentityTdscdma extends CellIdentity { } /** @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 031fed13d9f1..556bc32e7c36 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 @@ public final class CellIdentityWcdma extends CellIdentity { } /** @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 9f75332c4a03..bfa6326c3c18 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 @@ public final class PreciseCallState implements Parcelable { 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 60fda0906948..a96325e55416 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1950,14 +1950,9 @@ public class TelephonyManager { 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 97b24aef4af5..0baac71ffb68 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.service.carrier.CarrierIdentifier; 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 @@ interface ITelephony { */ 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 |