Merge "DO NOT MERGE - Merge QQ2A.200405.005 into master"
This commit is contained in:
@@ -1157,8 +1157,11 @@ public final class AssetManager implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
if (mObject != 0) {
|
||||
nativeDestroy(mObject);
|
||||
synchronized (this) {
|
||||
if (mObject != 0) {
|
||||
nativeDestroy(mObject);
|
||||
mObject = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -157,7 +157,6 @@ public class ExternalVibration implements Parcelable {
|
||||
out.writeInt(mUid);
|
||||
out.writeString(mPkg);
|
||||
writeAudioAttributes(mAttrs, out, flags);
|
||||
out.writeParcelable(mAttrs, flags);
|
||||
out.writeStrongBinder(mController.asBinder());
|
||||
out.writeStrongBinder(mToken);
|
||||
}
|
||||
|
||||
@@ -92,10 +92,7 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -424,13 +421,6 @@ public final class InputMethodManager {
|
||||
int mCursorCandStart;
|
||||
int mCursorCandEnd;
|
||||
|
||||
/**
|
||||
* Initial startInput with {@link StartInputReason.WINDOW_FOCUS_GAIN} is executed
|
||||
* in a background thread. Later, if there is an actual startInput it will wait on
|
||||
* main thread till the background thread completes.
|
||||
*/
|
||||
private CompletableFuture<Void> mWindowFocusGainFuture;
|
||||
|
||||
/**
|
||||
* The instance that has previously been sent to the input method.
|
||||
*/
|
||||
@@ -655,14 +645,14 @@ public final class InputMethodManager {
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check focus again in case that "onWindowFocus" is called before
|
||||
// handling this message.
|
||||
if (mServedView != null && canStartInput(mServedView)) {
|
||||
if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) {
|
||||
final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
|
||||
: StartInputReason.DEACTIVATED_BY_IMMS;
|
||||
startInputInner(reason, null, 0, 0, 0);
|
||||
// Check focus again in case that "onWindowFocus" is called before
|
||||
// handling this message.
|
||||
if (mServedView != null && canStartInput(mServedView)) {
|
||||
if (checkFocusNoStartInput(mRestartOnNextWindowFocus)) {
|
||||
final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
|
||||
: StartInputReason.DEACTIVATED_BY_IMMS;
|
||||
startInputInner(reason, null, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -1225,10 +1215,6 @@ public final class InputMethodManager {
|
||||
*/
|
||||
void clearBindingLocked() {
|
||||
if (DEBUG) Log.v(TAG, "Clearing binding!");
|
||||
if (mWindowFocusGainFuture != null) {
|
||||
mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
|
||||
mWindowFocusGainFuture = null;
|
||||
}
|
||||
clearConnectionLocked();
|
||||
setInputChannelLocked(null);
|
||||
mBindSequence = -1;
|
||||
@@ -1612,18 +1598,6 @@ public final class InputMethodManager {
|
||||
boolean startInputInner(@StartInputReason int startInputReason,
|
||||
@Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
|
||||
@SoftInputModeFlags int softInputMode, int windowFlags) {
|
||||
if (startInputReason != StartInputReason.WINDOW_FOCUS_GAIN
|
||||
&& mWindowFocusGainFuture != null) {
|
||||
try {
|
||||
mWindowFocusGainFuture.get();
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
// do nothing
|
||||
} catch (CancellationException e) {
|
||||
// window no longer has focus.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
final View view;
|
||||
synchronized (mH) {
|
||||
view = mServedView;
|
||||
@@ -1977,38 +1951,31 @@ public final class InputMethodManager {
|
||||
startInputFlags |= StartInputFlags.FIRST_WINDOW_FOCUS_GAIN;
|
||||
}
|
||||
|
||||
final boolean forceNewFocus1 = forceNewFocus;
|
||||
final int startInputFlags1 = startInputFlags;
|
||||
if (mWindowFocusGainFuture != null) {
|
||||
mWindowFocusGainFuture.cancel(false/* mayInterruptIfRunning */);
|
||||
if (checkFocusNoStartInput(forceNewFocus)) {
|
||||
// We need to restart input on the current focus view. This
|
||||
// should be done in conjunction with telling the system service
|
||||
// about the window gaining focus, to help make the transition
|
||||
// smooth.
|
||||
if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
|
||||
startInputFlags, softInputMode, windowFlags)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mWindowFocusGainFuture = CompletableFuture.runAsync(() -> {
|
||||
if (checkFocusNoStartInput(forceNewFocus1)) {
|
||||
// We need to restart input on the current focus view. This
|
||||
// should be done in conjunction with telling the system service
|
||||
// about the window gaining focus, to help make the transition
|
||||
// smooth.
|
||||
if (startInputInner(StartInputReason.WINDOW_FOCUS_GAIN, rootView.getWindowToken(),
|
||||
startInputFlags1, softInputMode, windowFlags)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// For some reason we didn't do a startInput + windowFocusGain, so
|
||||
// we'll just do a window focus gain and call it a day.
|
||||
synchronized (mH) {
|
||||
try {
|
||||
if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
|
||||
mService.startInputOrWindowGainedFocus(
|
||||
StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
|
||||
rootView.getWindowToken(), startInputFlags1, softInputMode, windowFlags,
|
||||
null, null, 0 /* missingMethodFlags */,
|
||||
rootView.getContext().getApplicationInfo().targetSdkVersion);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
// For some reason we didn't do a startInput + windowFocusGain, so
|
||||
// we'll just do a window focus gain and call it a day.
|
||||
synchronized (mH) {
|
||||
try {
|
||||
if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
|
||||
mService.startInputOrWindowGainedFocus(
|
||||
StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
|
||||
rootView.getWindowToken(), startInputFlags, softInputMode, windowFlags,
|
||||
null, null, 0 /* missingMethodFlags */,
|
||||
rootView.getContext().getApplicationInfo().targetSdkVersion);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@@ -2023,10 +1990,6 @@ public final class InputMethodManager {
|
||||
// If the mCurRootView is losing window focus, release the strong reference to it
|
||||
// so as not to prevent it from being garbage-collected.
|
||||
mCurRootView = null;
|
||||
if (mWindowFocusGainFuture != null) {
|
||||
mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
|
||||
mWindowFocusGainFuture = null;
|
||||
}
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.v(TAG, "Ignoring onPreWindowFocus()."
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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 android.os;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import android.media.AudioAttributes;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ExternalVibrationTest {
|
||||
@Test
|
||||
public void testSerialization() {
|
||||
AudioAttributes audio = new AudioAttributes.Builder().build();
|
||||
IExternalVibrationController controller = mock(IExternalVibrationController.class);
|
||||
ExternalVibration original = new ExternalVibration(
|
||||
123, // uid
|
||||
"pkg",
|
||||
audio,
|
||||
controller);
|
||||
Parcel p = Parcel.obtain();
|
||||
original.writeToParcel(p, 0);
|
||||
p.setDataPosition(0);
|
||||
ExternalVibration restored = ExternalVibration.CREATOR.createFromParcel(p);
|
||||
assertEquals(original, restored);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,20 +195,32 @@ public class AppOpsControllerImpl implements AppOpsController,
|
||||
mNotedItems.remove(item);
|
||||
if (DEBUG) Log.w(TAG, "Removed item: " + item.toString());
|
||||
}
|
||||
notifySuscribers(code, uid, packageName, false);
|
||||
boolean active;
|
||||
// Check if the item is also active
|
||||
synchronized (mActiveItems) {
|
||||
active = getAppOpItem(mActiveItems, code, uid, packageName) != null;
|
||||
}
|
||||
if (!active) {
|
||||
notifySuscribers(code, uid, packageName, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void addNoted(int code, int uid, String packageName) {
|
||||
private boolean addNoted(int code, int uid, String packageName) {
|
||||
AppOpItem item;
|
||||
boolean createdNew = false;
|
||||
synchronized (mNotedItems) {
|
||||
item = getAppOpItem(mNotedItems, code, uid, packageName);
|
||||
if (item == null) {
|
||||
item = new AppOpItem(code, uid, packageName, System.currentTimeMillis());
|
||||
mNotedItems.add(item);
|
||||
if (DEBUG) Log.w(TAG, "Added item: " + item.toString());
|
||||
createdNew = true;
|
||||
}
|
||||
}
|
||||
// We should keep this so we make sure it cannot time out.
|
||||
mBGHandler.removeCallbacksAndMessages(item);
|
||||
mBGHandler.scheduleRemoval(item, NOTED_OP_TIME_DELAY_MS);
|
||||
return createdNew;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -255,23 +267,46 @@ public class AppOpsControllerImpl implements AppOpsController,
|
||||
|
||||
@Override
|
||||
public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
|
||||
if (updateActives(code, uid, packageName, active)) {
|
||||
notifySuscribers(code, uid, packageName, active);
|
||||
if (DEBUG) {
|
||||
Log.w(TAG, String.format("onActiveChanged(%d,%d,%s,%s", code, uid, packageName,
|
||||
Boolean.toString(active)));
|
||||
}
|
||||
boolean activeChanged = updateActives(code, uid, packageName, active);
|
||||
if (!activeChanged) return; // early return
|
||||
// Check if the item is also noted, in that case, there's no update.
|
||||
boolean alsoNoted;
|
||||
synchronized (mNotedItems) {
|
||||
alsoNoted = getAppOpItem(mNotedItems, code, uid, packageName) != null;
|
||||
}
|
||||
// If active is true, we only send the update if the op is not actively noted (already true)
|
||||
// If active is false, we only send the update if the op is not actively noted (prevent
|
||||
// early removal)
|
||||
if (!alsoNoted) {
|
||||
mBGHandler.post(() -> notifySuscribers(code, uid, packageName, active));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpNoted(int code, int uid, String packageName, int result) {
|
||||
if (DEBUG) {
|
||||
Log.w(TAG, "Op: " + code + " with result " + AppOpsManager.MODE_NAMES[result]);
|
||||
Log.w(TAG, "Noted op: " + code + " with result "
|
||||
+ AppOpsManager.MODE_NAMES[result] + " for package " + packageName);
|
||||
}
|
||||
if (result != AppOpsManager.MODE_ALLOWED) return;
|
||||
addNoted(code, uid, packageName);
|
||||
notifySuscribers(code, uid, packageName, true);
|
||||
boolean notedAdded = addNoted(code, uid, packageName);
|
||||
if (!notedAdded) return; // early return
|
||||
boolean alsoActive;
|
||||
synchronized (mActiveItems) {
|
||||
alsoActive = getAppOpItem(mActiveItems, code, uid, packageName) != null;
|
||||
}
|
||||
if (!alsoActive) {
|
||||
mBGHandler.post(() -> notifySuscribers(code, uid, packageName, true));
|
||||
}
|
||||
}
|
||||
|
||||
private void notifySuscribers(int code, int uid, String packageName, boolean active) {
|
||||
if (mCallbacksByCode.containsKey(code)) {
|
||||
if (DEBUG) Log.d(TAG, "Notifying of change in package " + packageName);
|
||||
for (Callback cb: mCallbacksByCode.get(code)) {
|
||||
cb.onActiveStateChanged(code, uid, packageName, active);
|
||||
}
|
||||
@@ -295,7 +330,7 @@ public class AppOpsControllerImpl implements AppOpsController,
|
||||
|
||||
}
|
||||
|
||||
protected final class H extends Handler {
|
||||
protected class H extends Handler {
|
||||
H(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserHandle;
|
||||
@@ -36,7 +38,6 @@ import android.testing.TestableLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.Dependency;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -45,6 +46,8 @@ import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
@TestableLooper.RunWithLooper
|
||||
@@ -63,14 +66,16 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
||||
private AppOpsControllerImpl.H mMockHandler;
|
||||
|
||||
private AppOpsControllerImpl mController;
|
||||
private TestableLooper mTestableLooper;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mTestableLooper = TestableLooper.get(this);
|
||||
|
||||
getContext().addMockSystemService(AppOpsManager.class, mAppOpsManager);
|
||||
|
||||
mController = new AppOpsControllerImpl(mContext, Dependency.get(Dependency.BG_LOOPER));
|
||||
mController = new AppOpsControllerImpl(mContext, mTestableLooper.getLooper());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -94,6 +99,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
||||
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
|
||||
TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
}
|
||||
@@ -103,6 +109,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
||||
mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCallback, never()).onActiveStateChanged(
|
||||
anyInt(), anyInt(), anyString(), anyBoolean());
|
||||
}
|
||||
@@ -113,6 +120,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
||||
mController.removeCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCallback, never()).onActiveStateChanged(
|
||||
anyInt(), anyInt(), anyString(), anyBoolean());
|
||||
}
|
||||
@@ -123,6 +131,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
||||
mController.removeCallback(new int[]{AppOpsManager.OP_CAMERA}, mCallback);
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
|
||||
TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
}
|
||||
@@ -185,4 +194,129 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
||||
verify(mMockHandler).removeCallbacksAndMessages(null);
|
||||
assertTrue(mController.getActiveAppOps().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noDoubleUpdateOnOpNoted() {
|
||||
mController.setBGHandler(mMockHandler);
|
||||
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
// Only one post to notify subscribers
|
||||
verify(mMockHandler, times(1)).post(any());
|
||||
|
||||
List<AppOpItem> list = mController.getActiveAppOps();
|
||||
assertEquals(1, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDoubleOPNoted_scheduleTwiceForRemoval() {
|
||||
mController.setBGHandler(mMockHandler);
|
||||
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
// Only one post to notify subscribers
|
||||
verify(mMockHandler, times(2)).scheduleRemoval(any(), anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActiveOpNotRemovedAfterNoted() throws InterruptedException {
|
||||
// Replaces the timeout delay with 5 ms
|
||||
AppOpsControllerImpl.H testHandler = mController.new H(mTestableLooper.getLooper()) {
|
||||
@Override
|
||||
public void scheduleRemoval(AppOpItem item, long timeToRemoval) {
|
||||
super.scheduleRemoval(item, 5L);
|
||||
}
|
||||
};
|
||||
|
||||
mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
|
||||
mController.setBGHandler(testHandler);
|
||||
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
List<AppOpItem> list = mController.getActiveAppOps();
|
||||
verify(mCallback).onActiveStateChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
|
||||
// Duplicates are not removed between active and noted
|
||||
assertEquals(2, list.size());
|
||||
|
||||
sleep(10L);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mCallback, never()).onActiveStateChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, false);
|
||||
list = mController.getActiveAppOps();
|
||||
assertEquals(1, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotedNotRemovedAfterActive() {
|
||||
mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
|
||||
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
List<AppOpItem> list = mController.getActiveAppOps();
|
||||
verify(mCallback).onActiveStateChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
|
||||
// Duplicates are not removed between active and noted
|
||||
assertEquals(2, list.size());
|
||||
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, false);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
|
||||
verify(mCallback, never()).onActiveStateChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, false);
|
||||
list = mController.getActiveAppOps();
|
||||
assertEquals(1, list.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotedAndActiveOnlyOneCall() {
|
||||
mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
|
||||
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCallback).onActiveStateChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testActiveAndNotedOnlyOneCall() {
|
||||
mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
|
||||
|
||||
mController.onOpActiveChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
|
||||
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
|
||||
AppOpsManager.MODE_ALLOWED);
|
||||
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mCallback).onActiveStateChanged(
|
||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class GnssConfiguration {
|
||||
|
||||
// Represents an HAL interface version. Instances of this class are created in the JNI layer
|
||||
// and returned through native methods.
|
||||
private static class HalInterfaceVersion {
|
||||
static class HalInterfaceVersion {
|
||||
final int mMajor;
|
||||
final int mMinor;
|
||||
|
||||
@@ -205,6 +205,10 @@ class GnssConfiguration {
|
||||
native_set_satellite_blacklist(constellations, svids);
|
||||
}
|
||||
|
||||
HalInterfaceVersion getHalInterfaceVersion() {
|
||||
return native_get_gnss_configuration_version();
|
||||
}
|
||||
|
||||
interface SetCarrierProperty {
|
||||
boolean set(int value);
|
||||
}
|
||||
@@ -231,8 +235,7 @@ class GnssConfiguration {
|
||||
|
||||
logConfigurations();
|
||||
|
||||
final HalInterfaceVersion gnssConfigurationIfaceVersion =
|
||||
native_get_gnss_configuration_version();
|
||||
final HalInterfaceVersion gnssConfigurationIfaceVersion = getHalInterfaceVersion();
|
||||
if (gnssConfigurationIfaceVersion != null) {
|
||||
// Set to a range checked value.
|
||||
if (isConfigEsExtensionSecSupported(gnssConfigurationIfaceVersion)
|
||||
|
||||
@@ -774,10 +774,15 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
|
||||
|
||||
locationRequest.setProvider(provider);
|
||||
|
||||
// Ignore location settings if in emergency mode.
|
||||
if (isUserEmergency && mNIHandler.getInEmergency()) {
|
||||
locationRequest.setLocationSettingsIgnored(true);
|
||||
durationMillis *= EMERGENCY_LOCATION_UPDATE_DURATION_MULTIPLIER;
|
||||
// Ignore location settings if in emergency mode. This is only allowed for
|
||||
// isUserEmergency request (introduced in HAL v2.0), or DBH request in HAL v1.1.
|
||||
if (mNIHandler.getInEmergency()) {
|
||||
GnssConfiguration.HalInterfaceVersion halVersion =
|
||||
mGnssConfiguration.getHalInterfaceVersion();
|
||||
if (isUserEmergency || (halVersion.mMajor < 2 && !independentFromGnss)) {
|
||||
locationRequest.setLocationSettingsIgnored(true);
|
||||
durationMillis *= EMERGENCY_LOCATION_UPDATE_DURATION_MULTIPLIER;
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG,
|
||||
|
||||
@@ -17556,36 +17556,48 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
int count = 0;
|
||||
final String packageName = pkg.packageName;
|
||||
|
||||
boolean handlesWebUris = false;
|
||||
final boolean alreadyVerified;
|
||||
synchronized (mPackages) {
|
||||
// If this is a new install and we see that we've already run verification for this
|
||||
// package, we have nothing to do: it means the state was restored from backup.
|
||||
if (!replacing) {
|
||||
IntentFilterVerificationInfo ivi =
|
||||
mSettings.getIntentFilterVerificationLPr(packageName);
|
||||
if (ivi != null) {
|
||||
if (DEBUG_DOMAIN_VERIFICATION) {
|
||||
Slog.i(TAG, "Package " + packageName+ " already verified: status="
|
||||
+ ivi.getStatusString());
|
||||
}
|
||||
return;
|
||||
final IntentFilterVerificationInfo ivi =
|
||||
mSettings.getIntentFilterVerificationLPr(packageName);
|
||||
alreadyVerified = (ivi != null);
|
||||
if (!replacing && alreadyVerified) {
|
||||
if (DEBUG_DOMAIN_VERIFICATION) {
|
||||
Slog.i(TAG, "Package " + packageName + " already verified: status="
|
||||
+ ivi.getStatusString());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If any filters need to be verified, then all need to be.
|
||||
// If any filters need to be verified, then all need to be. In addition, we need to
|
||||
// know whether an updating app has any web navigation intent filters, to re-
|
||||
// examine handling policy even if not re-verifying.
|
||||
boolean needToVerify = false;
|
||||
for (PackageParser.Activity a : pkg.activities) {
|
||||
for (ActivityIntentInfo filter : a.intents) {
|
||||
if (filter.handlesWebUris(true)) {
|
||||
handlesWebUris = true;
|
||||
}
|
||||
if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
|
||||
if (DEBUG_DOMAIN_VERIFICATION) {
|
||||
Slog.d(TAG,
|
||||
"Intent filter needs verification, so processing all filters");
|
||||
}
|
||||
needToVerify = true;
|
||||
// It's safe to break out here because filter.needsVerification()
|
||||
// can only be true if filter.handlesWebUris(true) returns true, so
|
||||
// we've already noted that.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Note whether this app publishes any web navigation handling support at all,
|
||||
// and whether there are any web-nav filters that fit the profile for running
|
||||
// a verification pass now.
|
||||
if (needToVerify) {
|
||||
final int verificationId = mIntentFilterVerificationToken++;
|
||||
for (PackageParser.Activity a : pkg.activities) {
|
||||
@@ -17603,13 +17615,23 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
// count > 0 means that we're running a full verification pass
|
||||
if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
|
||||
+ " IntentFilter verification" + (count > 1 ? "s" : "")
|
||||
+ " for userId:" + userId);
|
||||
mIntentFilterVerifier.startVerifications(userId);
|
||||
} else if (alreadyVerified && handlesWebUris) {
|
||||
// App used autoVerify in the past, no longer does, but still handles web
|
||||
// navigation starts.
|
||||
if (DEBUG_DOMAIN_VERIFICATION) {
|
||||
Slog.d(TAG, "App changed web filters but no longer verifying - resetting policy");
|
||||
}
|
||||
synchronized (mPackages) {
|
||||
clearIntentFilterVerificationsLPw(packageName, userId);
|
||||
}
|
||||
} else {
|
||||
if (DEBUG_DOMAIN_VERIFICATION) {
|
||||
Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
|
||||
Slog.d(TAG, "No web filters or no prior verify policy for " + packageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1252,6 +1252,7 @@ public final class Settings {
|
||||
return false;
|
||||
}
|
||||
ps.clearDomainVerificationStatusForUser(userId);
|
||||
ps.setIntentFilterVerificationInfo(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user