diff options
26 files changed, 482 insertions, 153 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index b2a47f294a74..123ca5109696 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5920,6 +5920,7 @@ package android.telephony.euicc { field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2 field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1 field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4 + field public static final int RESULT_CALLER_NOT_ALLOWED = -3; // 0xfffffffd field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe field public static final int RESULT_OK = 0; // 0x0 field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 689f975c91ca..a30e38aeed0c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -11499,6 +11499,24 @@ public final class Settings { public static final String NETWORK_WATCHLIST_ENABLED = "network_watchlist_enabled"; /** + * Whether or not show hidden launcher icon apps feature is enabled. + * Type: int (0 for false, 1 for true) + * Default: 0 + * @hide + */ + public static final String SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED = + "show_hidden_icon_apps_enabled"; + + /** + * Whether or not show new app installed notification is enabled. + * Type: int (0 for false, 1 for true) + * Default: 0 + * @hide + */ + public static final String SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED = + "show_new_app_installed_notification_enabled"; + + /** * Flag to keep background restricted profiles running after exiting. If disabled, * the restricted profile can be put into stopped state as soon as the user leaves it. * Type: int (0 for false, 1 for true) @@ -12490,6 +12508,17 @@ public final class Settings { "privileged_device_identifier_target_q_behavior_enabled"; /** + * If set to 1, the device identifier check will be relaxed to the previous READ_PHONE_STATE + * permission check for 3P apps. + * + * STOPSHIP: Remove this once we ship with the new device identifier check enabled. + * + * @hide + */ + public static final String PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED = + "privileged_device_identifier_3p_check_relaxed"; + + /** * If set to 1, SettingsProvider's restoreAnyVersion="true" attribute will be ignored * and restoring to lower version of platform API will be skipped. * diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java index 2d60d28f6d3a..4a7e783ffbdb 100644 --- a/core/java/android/view/WindowInsets.java +++ b/core/java/android/view/WindowInsets.java @@ -384,6 +384,7 @@ public final class WindowInsets { displayCutoutCopyConstructorArgument(this)); } + // TODO(b/119190588): replace @code with @link below /** * Returns a copy of this WindowInsets with selected system window insets replaced * with new values. @@ -398,7 +399,7 @@ public final class WindowInsets { * @param right New right inset in pixels * @param bottom New bottom inset in pixels * @return A modified copy of this WindowInsets - * @deprecated use {@link Builder#Builder(WindowInsets)} with + * @deprecated use {@code Builder#Builder(WindowInsets)} with * {@link Builder#setSystemWindowInsets(Insets)} instead. */ @Deprecated @@ -414,6 +415,7 @@ public final class WindowInsets { return new Builder(this).setSystemWindowInsets(Insets.of(left, top, right, bottom)).build(); } + // TODO(b/119190588): replace @code with @link below /** * Returns a copy of this WindowInsets with selected system window insets replaced * with new values. @@ -426,7 +428,7 @@ public final class WindowInsets { * @param systemWindowInsets New system window insets. Each field is the inset in pixels * for that edge * @return A modified copy of this WindowInsets - * @deprecated use {@link Builder#Builder(WindowInsets)} with + * @deprecated use {@code Builder#Builder(WindowInsets)} with * {@link Builder#setSystemWindowInsets(Insets)} instead. */ @Deprecated diff --git a/core/proto/OWNERS b/core/proto/OWNERS index 2ace1ac491c7..480b1eaaf98c 100644 --- a/core/proto/OWNERS +++ b/core/proto/OWNERS @@ -11,6 +11,9 @@ yanglu@google.com yaochen@google.com yro@google.com +# Settings UI +per-file settings_enums.proto=zhfan@google.com + # Frameworks ogunwale@google.com jjaggi@google.com diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto index 307297781a60..69ebb59ffda4 100644 --- a/core/proto/android/providers/settings/global.proto +++ b/core/proto/android/providers/settings/global.proto @@ -725,8 +725,10 @@ message GlobalSettingsProto { optional SettingProto set_install_location = 103 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto shortcut_manager_constants = 104; optional SettingProto show_first_crash_dialog = 105 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_hidden_launcher_icon_apps_enabled = 141 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto show_restart_in_crash_dialog = 106 [ (android.privacy).dest = DEST_AUTOMATIC ]; optional SettingProto show_mute_in_crash_dialog = 107 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingProto show_new_app_installed_notification_enabled = 142 [ (android.privacy).dest = DEST_AUTOMATIC ]; message SmartSelection { option (android.msg_privacy).dest = DEST_EXPLICIT; @@ -966,5 +968,5 @@ message GlobalSettingsProto { // Please insert fields in alphabetical order and group them into messages // if possible (to avoid reaching the method limit). - // Next tag = 141; + // Next tag = 143; } diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java index 4980210feb66..d5dc9034ef85 100644 --- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java +++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java @@ -370,6 +370,7 @@ public class SettingsBackupTest { Settings.Global.PRIVATE_DNS_DEFAULT_MODE, Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED, + Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED, Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS, Settings.Global.RADIO_BLUETOOTH, Settings.Global.RADIO_CELL, @@ -393,7 +394,9 @@ public class SettingsBackupTest { Settings.Global.SETTINGS_USE_PSD_API, Settings.Global.SHORTCUT_MANAGER_CONSTANTS, Settings.Global.SHOW_FIRST_CRASH_DIALOG, + Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG, + Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED, Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG, Settings.Global.SHOW_TEMPERATURE_WARNING, diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 288ba32c47a6..9e6948878b1d 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -162,6 +162,13 @@ void AssetManager2::DumpToLog() const { LOG(INFO) << base::StringPrintf("PG (%02x): ", package_group.dynamic_ref_table.mAssignedPackageId) << list; + + for (size_t i = 0; i < 256; i++) { + if (package_group.dynamic_ref_table.mLookupTable[i] != 0) { + LOG(INFO) << base::StringPrintf(" e[0x%02x] -> 0x%02x", (uint8_t) i, + package_group.dynamic_ref_table.mLookupTable[i]); + } + } } } diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index dc4a0a706bae..388548b174f9 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -6998,18 +6998,28 @@ status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { } status_t DynamicRefTable::lookupResourceValue(Res_value* value) const { - uint8_t resolvedType; - - if (value->dataType == Res_value::TYPE_ATTRIBUTE - || value->dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE) { - resolvedType = Res_value::TYPE_ATTRIBUTE; - - } else if (value->dataType == Res_value::TYPE_REFERENCE - || value->dataType == Res_value::TYPE_DYNAMIC_REFERENCE) { - resolvedType = Res_value::TYPE_REFERENCE; + uint8_t resolvedType = Res_value::TYPE_REFERENCE; + switch (value->dataType) { + case Res_value::TYPE_ATTRIBUTE: + resolvedType = Res_value::TYPE_ATTRIBUTE; + // fallthrough + case Res_value::TYPE_REFERENCE: + // Only resolve non-dynamic references and attributes if the package is loaded as a + // library or if a shared library is attempting to retrieve its own resource + if (!(mAppAsLib || (Res_GETPACKAGE(value->data) + 1) == 0)) { + return NO_ERROR; + } - } else { - return NO_ERROR; + // If the package is loaded as shared library, the resource reference + // also need to be fixed. + break; + case Res_value::TYPE_DYNAMIC_ATTRIBUTE: + resolvedType = Res_value::TYPE_ATTRIBUTE; + // fallthrough + case Res_value::TYPE_DYNAMIC_REFERENCE: + break; + default: + return NO_ERROR; } status_t err = lookupResourceId(&value->data); diff --git a/libs/androidfw/tests/DynamicRefTable_test.cpp b/libs/androidfw/tests/DynamicRefTable_test.cpp index df44e343b2b4..5acc46a3c0d9 100644 --- a/libs/androidfw/tests/DynamicRefTable_test.cpp +++ b/libs/androidfw/tests/DynamicRefTable_test.cpp @@ -40,6 +40,26 @@ TEST(DynamicRefTableTest, LookupSharedLibSelfReferences) { EXPECT_EQ(value2.data, 0x02010000); }; +TEST(DynamicRefTableTest, LookupSharedLibSelfAttributes) { + // Shared library + DynamicRefTable shared_table(0x03, /* appAsLib */ false); + shared_table.addMapping(0x00, 0x03); + Res_value value; + value.dataType = Res_value::TYPE_ATTRIBUTE; + value.data = 0x00010000; + ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR); + EXPECT_EQ(value.data, 0x03010000); + + // App loaded as a shared library + DynamicRefTable shared_app_table(0x04, /* appAsLib */ true); + shared_app_table.addMapping(0x7f, 0x04); + Res_value value2; + value2.dataType = Res_value::TYPE_ATTRIBUTE; + value2.data = 0x7f010000; + ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR); + EXPECT_EQ(value2.data, 0x04010000); +}; + TEST(DynamicRefTableTest, LookupDynamicReferences) { // Shared library DynamicRefTable shared_table(0x2, /* appAsLib */ false); @@ -51,24 +71,46 @@ TEST(DynamicRefTableTest, LookupDynamicReferences) { ASSERT_EQ(shared_table.lookupResourceValue(&value), NO_ERROR); EXPECT_EQ(value.data, 0x05010000); - // App loaded as a shared library + // Regular application + DynamicRefTable app_table(0x7f, /* appAsLib */ false); + app_table.addMapping(0x03, 0x05); + Res_value value3; + value3.dataType = Res_value::TYPE_DYNAMIC_REFERENCE; + value3.data = 0x03010000; + ASSERT_EQ(app_table.lookupResourceValue(&value3), NO_ERROR); + EXPECT_EQ(value3.data, 0x05010000); +}; + +TEST(DynamicRefTableTest, LookupDynamicAttributes) { +// App loaded as a shared library DynamicRefTable shared_app_table(0x2, /* appAsLib */ true); shared_app_table.addMapping(0x03, 0x05); shared_app_table.addMapping(0x7f, 0x2); Res_value value2; - value2.dataType = Res_value::TYPE_DYNAMIC_REFERENCE; + value2.dataType = Res_value::TYPE_DYNAMIC_ATTRIBUTE; value2.data = 0x03010000; ASSERT_EQ(shared_app_table.lookupResourceValue(&value2), NO_ERROR); EXPECT_EQ(value2.data, 0x05010000); +} +TEST(DynamicRefTableTest, DoNotLookupNonDynamicReferences) { // Regular application DynamicRefTable app_table(0x7f, /* appAsLib */ false); - app_table.addMapping(0x03, 0x05); - Res_value value3; - value3.dataType = Res_value::TYPE_REFERENCE; - value3.data = 0x03010000; - ASSERT_EQ(app_table.lookupResourceValue(&value3), NO_ERROR); - EXPECT_EQ(value3.data, 0x05010000); + Res_value value; + value.dataType = Res_value::TYPE_REFERENCE; + value.data = 0x03010000; + ASSERT_EQ(app_table.lookupResourceValue(&value), NO_ERROR); + EXPECT_EQ(value.data, 0x03010000); +}; + +TEST(DynamicRefTableTest, DoNotLookupNonDynamicAttributes) { + // App with custom package id + DynamicRefTable custom_app_table(0x8f, /* appAsLib */ false); + Res_value value2; + value2.dataType = Res_value::TYPE_ATTRIBUTE; + value2.data = 0x03010000; + ASSERT_EQ(custom_app_table.lookupResourceValue(&value2), NO_ERROR); + EXPECT_EQ(value2.data, 0x03010000); }; } // namespace android
\ No newline at end of file diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java index 1eb423e53267..74c7b5809337 100644 --- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java +++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstalledReceiver.java @@ -20,6 +20,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.net.Uri; +import android.provider.Settings; import android.util.Log; /** @@ -29,11 +30,11 @@ public class PackageInstalledReceiver extends BroadcastReceiver { private static final String TAG = PackageInstalledReceiver.class.getSimpleName(); private static final boolean DEBUG = false; - private static final boolean APP_INSTALLED_NOTIFICATION_ENABLED = false; @Override public void onReceive(Context context, Intent intent) { - if (!APP_INSTALLED_NOTIFICATION_ENABLED) { + if (Settings.Global.getInt(context.getContentResolver(), + Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED, 0) == 0) { return; } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 2d43762b6863..b46c288bdb00 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1120,6 +1120,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.SHOW_FIRST_CRASH_DIALOG, GlobalSettingsProto.SHOW_FIRST_CRASH_DIALOG); + dumpSetting(s, p, + Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, + GlobalSettingsProto.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED); // Settings.Global.SHOW_PROCESSES intentionally excluded since it's deprecated. dumpSetting(s, p, Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG, @@ -1127,6 +1130,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Global.SHOW_MUTE_IN_CRASH_DIALOG, GlobalSettingsProto.SHOW_MUTE_IN_CRASH_DIALOG); + dumpSetting(s, p, + Settings.Global.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED, + GlobalSettingsProto.SHOW_NEW_APP_INSTALLED_NOTIFICATION_ENABLED); final long smartSelectToken = p.start(GlobalSettingsProto.SMART_SELECTION); dumpSetting(s, p, diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 7d09c0079ae8..6f5d6577f700 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2131,7 +2131,7 @@ <string name="app_info">App info</string> <!-- Action label for switching to a browser for an instant app [CHAR LIMIT=20] --> - <string name="go_to_web">Go to web</string> + <string name="go_to_web">Go to browser</string> <!-- Quick settings tile for toggling mobile data [CHAR LIMIT=20] --> <string name="mobile_data">Mobile data</string> diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index bb3bfc1cd3f1..e3584cf7493e 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -679,6 +679,7 @@ public class SwipeHelper implements Gefingerpoken { public boolean isDismissGesture(MotionEvent ev) { float translation = getTranslation(mCurrView); return ev.getActionMasked() == MotionEvent.ACTION_UP + && !mFalsingManager.isUnlockingDisabled() && !isFalseGesture(ev) && (swipedFastEnough() || swipedFarEnough()) && mCallback.canChildBeDismissedInDirection(mCurrView, translation > 0); } diff --git a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java index 69e347c9476d..4010c43f675e 100644 --- a/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java +++ b/packages/SystemUI/src/com/android/systemui/analytics/DataCollector.java @@ -16,6 +16,9 @@ package com.android.systemui.analytics; +import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session; +import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent; + import android.content.Context; import android.database.ContentObserver; import android.hardware.Sensor; @@ -36,9 +39,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session; -import static com.android.systemui.statusbar.phone.nano.TouchAnalyticsProto.Session.PhoneEvent; - /** * Tracks touch, sensor and phone events when the lockscreen is on. If the phone is unlocked * the data containing these events is saved to a file. This data is collected @@ -53,6 +53,8 @@ public class DataCollector implements SensorEventListener { private static final String COLLECT_BAD_TOUCHES = "data_collector_collect_bad_touches"; private static final String ALLOW_REJECTED_TOUCH_REPORTS = "data_collector_allow_rejected_touch_reports"; + private static final String DISABLE_UNLOCKING_FOR_FALSING_COLLECTION = + "data_collector_disable_unlocking"; private static final long TIMEOUT_MILLIS = 11000; // 11 seconds. public static final boolean DEBUG = false; @@ -65,11 +67,11 @@ public class DataCollector implements SensorEventListener { private SensorLoggerSession mCurrentSession = null; private boolean mEnableCollector = false; - private boolean mTimeoutActive = false; private boolean mCollectBadTouches = false; private boolean mCornerSwiping = false; private boolean mTrackingStarted = false; private boolean mAllowReportRejectedTouch = false; + private boolean mDisableUnlocking = false; private static DataCollector sInstance = null; @@ -98,6 +100,11 @@ public class DataCollector implements SensorEventListener { mSettingsObserver, UserHandle.USER_ALL); + mContext.getContentResolver().registerContentObserver( + Settings.Secure.getUriFor(DISABLE_UNLOCKING_FOR_FALSING_COLLECTION), false, + mSettingsObserver, + UserHandle.USER_ALL); + updateConfiguration(); } @@ -118,6 +125,9 @@ public class DataCollector implements SensorEventListener { mAllowReportRejectedTouch = Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt( mContext.getContentResolver(), ALLOW_REJECTED_TOUCH_REPORTS, 0); + mDisableUnlocking = mEnableCollector && Build.IS_DEBUGGABLE && 0 != Settings.Secure.getInt( + mContext.getContentResolver(), + DISABLE_UNLOCKING_FOR_FALSING_COLLECTION, 0); } private boolean sessionEntrypoint() { @@ -144,7 +154,7 @@ public class DataCollector implements SensorEventListener { SensorLoggerSession session = mCurrentSession; mCurrentSession = null; - if (mEnableCollector) { + if (mEnableCollector || mDisableUnlocking) { session.end(System.currentTimeMillis(), result); queueSession(session); } @@ -183,11 +193,11 @@ public class DataCollector implements SensorEventListener { byte[] b = Session.toByteArray(currentSession.toProto()); String dir = mContext.getFilesDir().getAbsolutePath(); if (currentSession.getResult() != Session.SUCCESS) { - if (!mCollectBadTouches) { + if (!mDisableUnlocking && !mCollectBadTouches) { return; } dir += "/bad_touches"; - } else { + } else if (!mDisableUnlocking) { dir += "/good_touches"; } @@ -208,19 +218,6 @@ public class DataCollector implements SensorEventListener { public synchronized void onSensorChanged(SensorEvent event) { if (isEnabled() && mCurrentSession != null) { mCurrentSession.addSensorEvent(event, System.nanoTime()); - enforceTimeout(); - } - } - - private void enforceTimeout() { - if (mTimeoutActive) { - if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis() - > TIMEOUT_MILLIS) { - onSessionEnd(Session.UNKNOWN); - if (DEBUG) { - Log.i(TAG, "Analytics timed out."); - } - } } } @@ -233,9 +230,12 @@ public class DataCollector implements SensorEventListener { * rejected touch report. */ public boolean isEnabled() { - return mEnableCollector || mAllowReportRejectedTouch; + return mEnableCollector || mAllowReportRejectedTouch || mDisableUnlocking; } + public boolean isUnlockingDisabled() { + return mDisableUnlocking; + } /** * @return true if the full data set for data gathering should be collected - including * extensive sensor data, which is is not normally included with rejected touch reports. @@ -450,7 +450,6 @@ public class DataCollector implements SensorEventListener { } mCurrentSession.addMotionEvent(event); mCurrentSession.setTouchArea(width, height); - enforceTimeout(); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java index 3d578c39d3c4..2c61da343763 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java @@ -201,6 +201,9 @@ public class FalsingManager implements SensorEventListener { return mHumanInteractionClassifier.isEnabled() || mDataCollector.isEnabled(); } + public boolean isUnlockingDisabled() { + return mDataCollector.isUnlockingDisabled(); + } /** * @return true if the classifier determined that this is not a human interacting with the phone */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java index 8526afd34514..8a86826cd01d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java @@ -128,7 +128,8 @@ public class DragDownHelper implements Gefingerpoken { } return true; case MotionEvent.ACTION_UP: - if (!isFalseTouch() && mDragDownCallback.onDraggedDown(mStartingChild, + if (!mFalsingManager.isUnlockingDisabled() && !isFalseTouch() + && mDragDownCallback.onDraggedDown(mStartingChild, (int) (y - mInitialTouchY))) { if (mStartingChild == null) { cancelExpansion(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java index 462201c6dac2..b3d0bf8abf62 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardDismissUtil.java @@ -35,7 +35,7 @@ public class KeyguardDismissUtil implements KeyguardDismissHandler { } /** - * Executes an action that requres the screen to be unlocked. + * Executes an action that requires the screen to be unlocked. * * <p>Must be called after {@link #setDismissHandler}. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 31facb79045e..f4c2e27ca272 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -582,7 +582,7 @@ public class NotificationPanelView extends PanelView implements int stackScrollerPadding; if (mBarState != StatusBarState.KEYGUARD) { stackScrollerPadding = (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight - + mQsNotificationTopPadding; + + mQsNotificationTopPadding; } else { int totalHeight = getHeight(); int bottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding); @@ -754,7 +754,7 @@ public class NotificationPanelView extends PanelView implements mQsExpandImmediate = true; mNotificationStackScroller.setShouldShowShelfOnly(true); } - if (isFullyCollapsed()){ + if (isFullyCollapsed()) { expand(true /* animate */); } else { flingSettings(0 /* velocity */, FLING_EXPAND); @@ -921,7 +921,7 @@ public class NotificationPanelView extends PanelView implements } private boolean flingExpandsQs(float vel) { - if (isFalseTouch()) { + if (mFalsingManager.isUnlockingDisabled() || isFalseTouch()) { return false; } if (Math.abs(vel) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) { @@ -1046,11 +1046,11 @@ public class NotificationPanelView extends PanelView implements final boolean stylusButtonClickDrag = action == MotionEvent.ACTION_DOWN && (event.isButtonPressed(MotionEvent.BUTTON_STYLUS_PRIMARY) - || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY)); + || event.isButtonPressed(MotionEvent.BUTTON_STYLUS_SECONDARY)); final boolean mouseButtonClickDrag = action == MotionEvent.ACTION_DOWN && (event.isButtonPressed(MotionEvent.BUTTON_SECONDARY) - || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY)); + || event.isButtonPressed(MotionEvent.BUTTON_TERTIARY)); return twoFingerDrag || stylusButtonClickDrag || mouseButtonClickDrag; } @@ -1321,12 +1321,12 @@ public class NotificationPanelView extends PanelView implements private final ValueAnimator.AnimatorUpdateListener mStatusBarAnimateAlphaListener = new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue(); - updateHeaderKeyguardAlpha(); - } - }; + @Override + public void onAnimationUpdate(ValueAnimator animation) { + mKeyguardStatusBarAnimateAlpha = (float) animation.getAnimatedValue(); + updateHeaderKeyguardAlpha(); + } + }; private void animateKeyguardStatusBarIn(long duration) { mKeyguardStatusBar.setVisibility(View.VISIBLE); @@ -1382,7 +1382,7 @@ public class NotificationPanelView extends PanelView implements if (keyguardFadingAway) { mKeyguardStatusView.animate() .setStartDelay(mKeyguardMonitor.getKeyguardFadingAwayDelay()) - .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration()/2) + .setDuration(mKeyguardMonitor.getKeyguardFadingAwayDuration() / 2) .start(); } } else if (mBarState == StatusBarState.SHADE_LOCKED @@ -1425,8 +1425,8 @@ public class NotificationPanelView extends PanelView implements updateEmptyShadeView(); mQsNavbarScrim.setVisibility(mBarState == StatusBarState.SHADE && mQsExpanded && !mStackScrollerOverscrolling && mQsScrimEnabled - ? View.VISIBLE - : View.INVISIBLE); + ? View.VISIBLE + : View.INVISIBLE); if (mKeyguardUserSwitcher != null && mQsExpanded && !mStackScrollerOverscrolling) { mKeyguardUserSwitcher.hideIfNotSimple(true /* animate */); } @@ -1459,7 +1459,8 @@ public class NotificationPanelView extends PanelView implements setAccessibilityPaneTitle(determineAccessibilityPaneTitle()); } - if (mQsFullyExpanded && mFalsingManager.shouldEnforceBouncer()) { + if (!mFalsingManager.isUnlockingDisabled() && mQsFullyExpanded + && mFalsingManager.shouldEnforceBouncer()) { mStatusBar.executeRunnableDismissingKeyguard(null, null /* cancelAction */, false /* dismissShade */, true /* afterKeyguardGone */, false /* deferred */); } @@ -2130,8 +2131,7 @@ public class NotificationPanelView extends PanelView implements } }, null, true /* dismissShade */, false /* afterKeyguardGone */, true /* deferred */); - } - else { + } else { mKeyguardBottomArea.launchLeftAffordance(); } } else { @@ -2588,7 +2588,7 @@ public class NotificationPanelView extends PanelView implements x = Math.min(rightMost, Math.max(leftMost, x)); setVerticalPanelTranslation(x - (mNotificationStackScroller.getLeft() + mNotificationStackScroller.getWidth() / 2)); - } + } private void resetVerticalPanelPosition() { setVerticalPanelTranslation(0f); @@ -2716,8 +2716,8 @@ public class NotificationPanelView extends PanelView implements String packageToLaunch = (resolveInfo == null || resolveInfo.activityInfo == null) ? null : resolveInfo.activityInfo.packageName; return packageToLaunch != null && - (keyguardIsShowing || !isForegroundApp(packageToLaunch)) && - !mAffordanceHelper.isSwipingInProgress(); + (keyguardIsShowing || !isForegroundApp(packageToLaunch)) + && !mAffordanceHelper.isSwipingInProgress(); } /** @@ -2884,13 +2884,14 @@ public class NotificationPanelView extends PanelView implements } public void setStatusAccessibilityImportance(int mode) { - mKeyguardStatusView.setImportantForAccessibility(mode); + mKeyguardStatusView.setImportantForAccessibility(mode); } /** * TODO: this should be removed. * It's not correct to pass this view forward because other classes will end up adding * children to it. Theme will be out of sync. + * * @return bottom area view */ public KeyguardBottomAreaView getKeyguardBottomAreaView() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index f29b7cab5cbc..021b4307aca4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -670,6 +670,10 @@ public abstract class PanelView extends FrameLayout { * @return whether a fling should expands the panel; contracts otherwise */ protected boolean flingExpands(float vel, float vectorVel, float x, float y) { + if (mFalsingManager.isUnlockingDisabled()) { + return true; + } + if (isFalseTouch(x, y)) { return true; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java new file mode 100644 index 000000000000..a8c1ac61e4cc --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2018 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.systemui.statusbar.phone; + +import static com.google.common.truth.Truth.assertThat; + +import android.support.test.filters.SmallTest; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase { + + private static final int SCREEN_HEIGHT = 2000; + private static final int EMPTY_MARGIN = 0; + private static final int EMPTY_HEIGHT = 0; + private static final boolean SECURE_LOCKED = false; + private static final boolean PULSING_NO = false; + private static final float ZERO_DRAG = 0.f; + private static final float OPAQUE = 1.f; + private static final float TRANSPARENT = 0.f; + + private KeyguardClockPositionAlgorithm mClockPositionAlgorithm; + private KeyguardClockPositionAlgorithm.Result mClockPosition; + private int mNotificationStackHeight; + private float mPanelExpansion; + private int mKeyguardStatusHeight; + private float mDark; + + @Before + public void setUp() { + mClockPositionAlgorithm = new KeyguardClockPositionAlgorithm(); + mClockPosition = new KeyguardClockPositionAlgorithm.Result(); + } + + @Test + public void clockPositionMiddleOfScreenOnAOD() { + // GIVEN on AOD and both stack scroll and clock have 0 height + givenAOD(); + mNotificationStackHeight = EMPTY_HEIGHT; + mKeyguardStatusHeight = EMPTY_HEIGHT; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2). + assertThat(mClockPosition.clockY).isEqualTo(1000); + // AND the clock is opaque and positioned on the left. + assertThat(mClockPosition.clockX).isEqualTo(0); + assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE); + } + + @Test + public void clockPositionAdjustsForKeyguardStatusOnAOD() { + // GIVEN on AOD with a clock of height 100 + givenAOD(); + mNotificationStackHeight = EMPTY_HEIGHT; + mKeyguardStatusHeight = 100; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock Y position adjusts for the clock height (SCREEN_HEIGHT / 2 - 100). + assertThat(mClockPosition.clockY).isEqualTo(900); + // AND the clock is opaque and positioned on the left. + assertThat(mClockPosition.clockX).isEqualTo(0); + assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE); + } + + @Test + public void clockPositionLargeClockOnAOD() { + // GIVEN on AOD with a full screen clock + givenAOD(); + mNotificationStackHeight = EMPTY_HEIGHT; + mKeyguardStatusHeight = SCREEN_HEIGHT; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock Y position overflows the parent. + assertThat(mClockPosition.clockY).isEqualTo(-1000); + // AND the clock is opaque and positioned on the left. + assertThat(mClockPosition.clockX).isEqualTo(0); + assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE); + } + + @Test + public void clockPositionMiddleOfScreenOnLockScreen() { + // GIVEN on lock screen with stack scroll and clock of 0 height + givenLockScreen(); + mNotificationStackHeight = EMPTY_HEIGHT; + mKeyguardStatusHeight = EMPTY_HEIGHT; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock Y position is the middle of the screen (SCREEN_HEIGHT / 2). + assertThat(mClockPosition.clockY).isEqualTo(1000); + // AND the clock is opaque and positioned on the left. + assertThat(mClockPosition.clockX).isEqualTo(0); + assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE); + } + + @Test + public void clockPositionWithStackScrollExpandOnLockScreen() { + // GIVEN on lock screen with stack scroll of height 500 + givenLockScreen(); + mNotificationStackHeight = 500; + mKeyguardStatusHeight = EMPTY_HEIGHT; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock Y position adjusts for stack scroll height ( (SCREEN_HEIGHT - 500 ) / 2). + assertThat(mClockPosition.clockY).isEqualTo(750); + // AND the clock is opaque and positioned on the left. + assertThat(mClockPosition.clockX).isEqualTo(0); + assertThat(mClockPosition.clockAlpha).isEqualTo(OPAQUE); + } + + @Test + public void clockPositionWithPartialDragOnLockScreen() { + // GIVEN dragging up on lock screen + givenLockScreen(); + mNotificationStackHeight = EMPTY_HEIGHT; + mKeyguardStatusHeight = EMPTY_HEIGHT; + mPanelExpansion = 0.5f; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock Y position adjusts with drag gesture. + assertThat(mClockPosition.clockY).isLessThan(1000); + // AND the clock is positioned on the left and not fully opaque. + assertThat(mClockPosition.clockX).isEqualTo(0); + assertThat(mClockPosition.clockAlpha).isLessThan(OPAQUE); + } + + @Test + public void clockPositionWithFullDragOnLockScreen() { + // GIVEN the lock screen is dragged up + givenLockScreen(); + mNotificationStackHeight = EMPTY_HEIGHT; + mKeyguardStatusHeight = EMPTY_HEIGHT; + mPanelExpansion = 0.f; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock is transparent. + assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT); + } + + @Test + public void largeClockOnLockScreenIsTransparent() { + // GIVEN on lock screen with a full screen clock + givenLockScreen(); + mNotificationStackHeight = EMPTY_HEIGHT; + mKeyguardStatusHeight = SCREEN_HEIGHT; + // WHEN the clock position algorithm is run + positionClock(); + // THEN the clock is transparent + assertThat(mClockPosition.clockAlpha).isEqualTo(TRANSPARENT); + } + + private void givenAOD() { + mPanelExpansion = 1.f; + mDark = 1.f; + } + + private void givenLockScreen() { + mPanelExpansion = 1.f; + mDark = 0.f; + } + + private void positionClock() { + mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight, + mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mDark, SECURE_LOCKED, + PULSING_NO, ZERO_DRAG); + mClockPositionAlgorithm.run(mClockPosition); + } +} diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index 6203340df588..275f3dcdb6d2 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -77,7 +77,6 @@ import java.util.List; */ public class LauncherAppsService extends SystemService { - private static final boolean SHOW_HIDDEN_APP_ENABLED = false; private final LauncherAppsImpl mLauncherAppsImpl; public LauncherAppsService(Context context) { @@ -310,7 +309,8 @@ public class LauncherAppsService extends SystemService { .addCategory(Intent.CATEGORY_LAUNCHER) .setPackage(packageName), user); - if (!SHOW_HIDDEN_APP_ENABLED) { + if (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.SHOW_HIDDEN_LAUNCHER_ICON_APPS_ENABLED, 0) == 0) { return launcherActivities; } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index 6e450137185b..249edab2be94 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -943,7 +943,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { IApexService apex = IApexService.Stub.asInterface( ServiceManager.getService("apexservice")); - apex.installPackage(mResolvedBaseFile.toString()); + apex.stagePackage(mResolvedBaseFile.toString()); } catch (Throwable e) { // Convert all exceptions into package manager exceptions as only those are handled // in the code above diff --git a/services/core/java/com/android/server/pm/permission/OWNERS b/services/core/java/com/android/server/pm/permission/OWNERS index ffc4731feadd..88b97ea2cb49 100644 --- a/services/core/java/com/android/server/pm/permission/OWNERS +++ b/services/core/java/com/android/server/pm/permission/OWNERS @@ -1,8 +1,9 @@ per-file DefaultPermissionGrantPolicy.java = bpoiesz@google.com -per-file DefaultPermissionGrantPolicy.java = fkupolov@google.com per-file DefaultPermissionGrantPolicy.java = hackbod@android.com per-file DefaultPermissionGrantPolicy.java = jsharkey@android.com per-file DefaultPermissionGrantPolicy.java = svetoslavganov@google.com per-file DefaultPermissionGrantPolicy.java = toddke@google.com per-file DefaultPermissionGrantPolicy.java = yamasani@google.com per-file DefaultPermissionGrantPolicy.java = patb@google.com +per-file DefaultPermissionGrantPolicy.java = eugenesusla@google.com +per-file DefaultPermissionGrantPolicy.java = moltmann@google.com diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 8a77f14345aa..1091b5839fe4 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1285,9 +1285,10 @@ public class TelephonyManager { * Returns the unique device ID, for example, the IMEI for GSM and the MEID * or ESN for CDMA phones. Return null if device ID is not available. * - * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the - * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app - * that owns a managed profile on the device; for more details see <a + * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or + * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier + * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a + * managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * @@ -1295,7 +1296,7 @@ public class TelephonyManager { * MEID for CDMA. */ @Deprecated - @SuppressAutoDoc // No support for device / profile owner. + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceId() { try { @@ -1314,9 +1315,10 @@ public class TelephonyManager { * Returns the unique device ID of a subscription, for example, the IMEI for * GSM and the MEID for CDMA phones. Return null if device ID is not available. * - * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the - * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app - * that owns a managed profile on the device; for more details see <a + * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or + * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier + * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a + * managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * @@ -1326,7 +1328,7 @@ public class TelephonyManager { * MEID for CDMA. */ @Deprecated - @SuppressAutoDoc // No support for device / profile owner. + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDeviceId(int slotIndex) { // FIXME this assumes phoneId == slotIndex @@ -1346,13 +1348,14 @@ public class TelephonyManager { * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not * available. * - * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the - * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app - * that owns a managed profile on the device; for more details see <a + * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or + * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier + * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a + * managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. */ - @SuppressAutoDoc // No support for device / profile owner. + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getImei() { return getImei(getSlotIndex()); @@ -1362,15 +1365,16 @@ public class TelephonyManager { * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not * available. * - * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the - * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app - * that owns a managed profile on the device; for more details see <a + * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or + * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier + * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a + * managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * * @param slotIndex of which IMEI is returned */ - @SuppressAutoDoc // No support for device / profile owner. + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getImei(int slotIndex) { ITelephony telephony = getITelephony(); @@ -1415,13 +1419,14 @@ public class TelephonyManager { /** * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available. * - * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the - * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app - * that owns a managed profile on the device; for more details see <a + * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or + * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier + * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a + * managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. */ - @SuppressAutoDoc // No support for device / profile owner. + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getMeid() { return getMeid(getSlotIndex()); @@ -1430,15 +1435,16 @@ public class TelephonyManager { /** * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available. * - * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, or for the calling package to be the - * device or profile owner and have the READ_PHONE_STATE permission. The profile owner is an app - * that owns a managed profile on the device; for more details see <a + * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE, for the calling app to be the device or + * profile owner and have the READ_PHONE_STATE permission, or that the calling app has carrier + * privileges (see {@link #hasCarrierPrivileges}). The profile owner is an app that owns a + * managed profile on the device; for more details see <a * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. * * @param slotIndex of which MEID is returned */ - @SuppressAutoDoc // No support for device / profile owner. + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getMeid(int slotIndex) { ITelephony telephony = getITelephony(); @@ -2936,7 +2942,7 @@ public class TelephonyManager { * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. */ - @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getSimSerialNumber() { return getSimSerialNumber(getSubId()); @@ -3098,7 +3104,7 @@ public class TelephonyManager { * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile owner * access is deprecated and will be removed in a future release. */ - @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges + @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236). @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getSubscriberId() { return getSubscriberId(getSubId()); diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java index 11411778a9ab..3b1ef3f45993 100644 --- a/telephony/java/android/telephony/euicc/EuiccCardManager.java +++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java @@ -15,6 +15,7 @@ */ package android.telephony.euicc; +import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.Nullable; import android.annotation.SystemApi; @@ -50,7 +51,6 @@ import com.android.internal.telephony.euicc.ISwitchToProfileCallback; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import android.annotation.CallbackExecutor; import java.util.concurrent.Executor; /** @@ -119,6 +119,9 @@ public class EuiccCardManager { /** Result code when the eUICC card with the given card Id is not found. */ public static final int RESULT_EUICC_NOT_FOUND = -2; + /** Result code indicating the caller is not the active LPA. */ + public static final int RESULT_CALLER_NOT_ALLOWED = -3; + /** * Callback to receive the result of an eUICC card API. * @@ -152,7 +155,7 @@ public class EuiccCardManager { * Requests all the profiles on eUicc. * * @param cardId The Id of the eUICC. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code and all the profiles. */ public void requestAllProfiles(String cardId, @CallbackExecutor Executor executor, @@ -176,7 +179,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code and profile. */ public void requestProfile(String cardId, String iccid, @CallbackExecutor Executor executor, @@ -201,7 +204,7 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. * @param refresh Whether sending the REFRESH command to modem. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code. */ public void disableProfile(String cardId, String iccid, boolean refresh, @@ -227,7 +230,7 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile to switch to. * @param refresh Whether sending the REFRESH command to modem. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code and the EuiccProfileInfo enabled. */ public void switchToProfile(String cardId, String iccid, boolean refresh, @@ -252,7 +255,7 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. * @param nickname The nickname of the profile. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code. */ public void setNickname(String cardId, String iccid, String nickname, @@ -276,7 +279,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param iccid The iccid of the profile. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code. */ public void deleteProfile(String cardId, String iccid, @CallbackExecutor Executor executor, @@ -301,7 +304,7 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param options Bits of the options of resetting which parts of the eUICC memory. See * EuiccCard for details. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code. */ public void resetMemory(String cardId, @ResetOption int options, @@ -324,7 +327,7 @@ public class EuiccCardManager { * Requests the default SM-DP+ address from eUICC. * * @param cardId The Id of the eUICC. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code and the default SM-DP+ address. */ public void requestDefaultSmdpAddress(String cardId, @CallbackExecutor Executor executor, @@ -347,7 +350,7 @@ public class EuiccCardManager { * Requests the SM-DS address from eUICC. * * @param cardId The Id of the eUICC. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code and the SM-DS address. */ public void requestSmdsAddress(String cardId, @CallbackExecutor Executor executor, @@ -371,7 +374,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param defaultSmdpAddress The default SM-DP+ address to set. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback The callback to get the result code. */ public void setDefaultSmdpAddress(String cardId, String defaultSmdpAddress, @@ -395,7 +398,7 @@ public class EuiccCardManager { * Requests Rules Authorisation Table. * * @param cardId The Id of the eUICC. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and the rule authorisation table. */ public void requestRulesAuthTable(String cardId, @CallbackExecutor Executor executor, @@ -418,7 +421,7 @@ public class EuiccCardManager { * Requests the eUICC challenge for new profile downloading. * * @param cardId The Id of the eUICC. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and the challenge. */ public void requestEuiccChallenge(String cardId, @CallbackExecutor Executor executor, @@ -441,7 +444,7 @@ public class EuiccCardManager { * Requests the eUICC info1 defined in GSMA RSP v2.0+ for new profile downloading. * * @param cardId The Id of the eUICC. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and the info1. */ public void requestEuiccInfo1(String cardId, @CallbackExecutor Executor executor, @@ -464,7 +467,7 @@ public class EuiccCardManager { * Gets the eUICC info2 defined in GSMA RSP v2.0+ for new profile downloading. * * @param cardId The Id of the eUICC. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and the info2. */ public void requestEuiccInfo2(String cardId, @CallbackExecutor Executor executor, @@ -497,7 +500,7 @@ public class EuiccCardManager { * GSMA RSP v2.0+. * @param serverCertificate ASN.1 data in byte array indicating SM-DP+ Certificate returned by * SM-DP+ server. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and a byte array which represents a * {@code AuthenticateServerResponse} defined in GSMA RSP v2.0+. */ @@ -537,7 +540,7 @@ public class EuiccCardManager { * SM-DP+ server. * @param smdpCertificate ASN.1 data in byte array indicating the SM-DP+ Certificate returned * by SM-DP+ server. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and a byte array which represents a * {@code PrepareDownloadResponse} defined in GSMA RSP v2.0+ */ @@ -569,7 +572,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param boundProfilePackage the Bound Profile Package data returned by SM-DP+ server. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and a byte array which represents a * {@code LoadBoundProfilePackageResponse} defined in GSMA RSP v2.0+. */ @@ -598,7 +601,7 @@ public class EuiccCardManager { * @param cardId The Id of the eUICC. * @param transactionId the transaction ID returned by SM-DP+ server. * @param reason the cancel reason. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and an byte[] which represents a * {@code CancelSessionResponse} defined in GSMA RSP v2.0+. */ @@ -627,7 +630,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param events bits of the event types ({@link EuiccNotification.Event}) to list. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and the list of notifications. */ public void listNotifications(String cardId, @EuiccNotification.Event int events, @@ -651,7 +654,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param events bits of the event types ({@link EuiccNotification.Event}) to list. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and the list of notifications. */ public void retrieveNotificationList(String cardId, @EuiccNotification.Event int events, @@ -675,7 +678,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param seqNumber the sequence number of the notification. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code and the notification. */ public void retrieveNotification(String cardId, int seqNumber, @@ -699,7 +702,7 @@ public class EuiccCardManager { * * @param cardId The Id of the eUICC. * @param seqNumber the sequence number of the notification. - * @param executor The executor through which the callback should be invode. + * @param executor The executor through which the callback should be invoke. * @param callback the callback to get the result code. */ public void removeNotificationFromList(String cardId, int seqNumber, diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java index eb6be65104d1..553e3fb9d219 100644 --- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java +++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java @@ -188,6 +188,13 @@ public final class TelephonyPermissions { if (checkReadDeviceIdentifiers(context, pid, uid, callingPackage)) { return true; } + // Calling packages with carrier privileges will also have access to device identifiers, but + // this may be removed in a future release. + if (SubscriptionManager.isValidSubscriptionId(subId) && getCarrierPrivilegeStatus( + TELEPHONY_SUPPLIER, subId, uid) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { + return true; + } // else the calling package is not authorized to access the device identifiers; call // a central method to report the failure based on the target SDK and if the calling package // has the READ_PHONE_STATE permission or carrier privileges that were previously required @@ -279,44 +286,51 @@ public final class TelephonyPermissions { int uid, String callingPackage, String message) { Log.wtf(LOG_TAG, "reportAccessDeniedToReadIdentifiers:" + callingPackage + ":" + message); - // if the device identifier check is relaxed then revert to the READ_PHONE_STATE permission - // check that was previously required to access device identifiers. - boolean relaxDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(), - Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, 0) == 0; - if (relaxDeviceIdentifierCheck) { - return checkReadPhoneState(context, subId, pid, uid, callingPackage, message); - } else { + // If the device identifier check is enabled then enforce the new access requirements for + // both 1P and 3P apps. + boolean enableDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_CHECK_ENABLED, 0) == 1; + // Check if the application is a 3P app; if so then a separate setting is required to relax + // the check to begin flagging problems with 3P apps early. + boolean relax3PDeviceIdentifierCheck = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_3P_CHECK_RELAXED, 0) == 1; + boolean is3PApp = true; + ApplicationInfo callingPackageInfo = null; + try { + callingPackageInfo = context.getPackageManager().getApplicationInfo(callingPackage, 0); + if (callingPackageInfo.isSystemApp()) { + is3PApp = false; + } + } catch (PackageManager.NameNotFoundException e) { + // If the application info for the calling package could not be found then assume the + // calling app is a 3P app to detect any issues with the check + } + if (enableDeviceIdentifierCheck || (is3PApp && !relax3PDeviceIdentifierCheck)) { boolean targetQBehaviorDisabled = Settings.Global.getInt(context.getContentResolver(), Settings.Global.PRIVILEGED_DEVICE_IDENTIFIER_TARGET_Q_BEHAVIOR_ENABLED, 0) == 0; if (callingPackage != null) { - try { - // if the target SDK is pre-Q or the target Q behavior is disabled then check if - // the calling package would have previously had access to device identifiers. - ApplicationInfo callingPackageInfo = - context.getPackageManager().getApplicationInfo( - callingPackage, 0); - if (callingPackageInfo != null && ( - callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q - || targetQBehaviorDisabled)) { - if (context.checkPermission( - android.Manifest.permission.READ_PHONE_STATE, - pid, - uid) == PackageManager.PERMISSION_GRANTED) { - return false; - } - if (SubscriptionManager.isValidSubscriptionId(subId) - && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid) - == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { - return false; - } + // if the target SDK is pre-Q or the target Q behavior is disabled then check if + // the calling package would have previously had access to device identifiers. + if (callingPackageInfo != null && ( + callingPackageInfo.targetSdkVersion < Build.VERSION_CODES.Q + || targetQBehaviorDisabled)) { + if (context.checkPermission( + android.Manifest.permission.READ_PHONE_STATE, + pid, + uid) == PackageManager.PERMISSION_GRANTED) { + return false; + } + if (SubscriptionManager.isValidSubscriptionId(subId) + && getCarrierPrivilegeStatus(TELEPHONY_SUPPLIER, subId, uid) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { + return false; } - } catch (PackageManager.NameNotFoundException e) { - // If the application info for the calling package could not be found then - // default to throwing the SecurityException. } } throw new SecurityException(message + ": The user " + uid + " does not meet the requirements to access device identifiers."); + } else { + return checkReadPhoneState(context, subId, pid, uid, callingPackage, message); } } |